0.5.1-pre.004
This commit is contained in:
37
.env.example
37
.env.example
@@ -3,36 +3,39 @@
|
|||||||
# Never commit the real .env file.
|
# Never commit the real .env file.
|
||||||
|
|
||||||
# Shared Helius credential used by the configured HTTP and WebSocket endpoints.
|
# Shared Helius credential used by the configured HTTP and WebSocket endpoints.
|
||||||
HELIUS_API_KEY=replace-with-your-helius-api-key
|
KS_SECRET_HELIUS_API_KEY=replace-with-your-helius-api-key
|
||||||
|
|
||||||
# PostgreSQL database used by the mainnet_research and mainnet profiles.
|
# PostgreSQL database used by the mainnet_research and mainnet profiles.
|
||||||
KB_POSTGRES_MAINNET_URL=postgres://solana:solana@localhost:5432/khadhroony_mainnet
|
KS_SECRET_POSTGRES_MAINNET_URL=postgres://solana:solana@localhost:5432/khadhroony_mainnet
|
||||||
|
|
||||||
# PostgreSQL database dedicated to the local_devnet profile and Devnet validation.
|
# PostgreSQL database dedicated to the local_devnet profile and Devnet validation.
|
||||||
KB_POSTGRES_DEVNET_URL=postgres://solana:solana@localhost:5432/khadhroony_devnet
|
KS_SECRET_POSTGRES_DEVNET_URL=postgres://solana:solana@localhost:5432/khadhroony_devnet
|
||||||
|
|
||||||
# PostgreSQL database reserved for automated integration tests.
|
# PostgreSQL database reserved for automated integration tests.
|
||||||
KB_POSTGRES_TEST_URL=postgres://solana:solana@localhost:5432/khadhroony_test
|
KS_SECRET_POSTGRES_TEST_URL=postgres://solana:solana@localhost:5432/khadhroony_test
|
||||||
|
|
||||||
# Optional configuration-file override.
|
# Optional configuration-file override.
|
||||||
# KB_CONFIG_PATH=config/example.config.json
|
# KS_CONFIG_PATH=config/example.config.json
|
||||||
|
|
||||||
# Optional Devnet profile selected by CLI and opt-in scenario tests.
|
# Optional Devnet profile selected by CLI and opt-in scenario tests.
|
||||||
# When absent, the first compatible Devnet profile is selected.
|
# When absent, the first compatible Devnet profile is selected.
|
||||||
# KB_DEVNET_PROFILE=local_devnet
|
# KS_DEVNET_PROFILE=local_devnet
|
||||||
|
|
||||||
# Optional Token-2022 Devnet validation fixtures.
|
# Optional Token-2022 Devnet validation fixtures.
|
||||||
TOKEN_2022_PROGRAM=TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
|
KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID=TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
|
||||||
TOKEN_2022_MINT=
|
KS_PUBLIC_DEVNET_TOKEN_2022_MINT=
|
||||||
TOKEN_2022_SOURCE=
|
KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE=
|
||||||
TOKEN_2022_DESTINATION=
|
KS_PUBLIC_DEVNET_TOKEN_2022_DESTINATION=
|
||||||
TOKEN_2022_CLOSE_ACCOUNT=
|
KS_PUBLIC_DEVNET_TOKEN_2022_CLOSE_ACCOUNT=
|
||||||
TOKEN_2022_DELEGATE=
|
KS_PUBLIC_DEVNET_TOKEN_2022_DELEGATE=
|
||||||
TOKEN_2022_AUTHORITY=
|
KS_PUBLIC_DEVNET_TOKEN_2022_AUTHORITY=
|
||||||
TOKEN_2022_FREEZE_AUTHORITY=
|
KS_PUBLIC_DEVNET_TOKEN_2022_FREEZE_AUTHORITY=
|
||||||
TOKEN_2022_DECIMALS=9
|
KS_PUBLIC_DEVNET_TOKEN_2022_DECIMALS=9
|
||||||
TOKEN_2022_TRANSFER_AMOUNT_RAW=1
|
KS_PUBLIC_DEVNET_TOKEN_2022_MINT_AMOUNT_RAW=10000000000
|
||||||
|
KS_PUBLIC_DEVNET_TOKEN_2022_TRANSFER_AMOUNT_RAW=1000000000
|
||||||
|
KS_PUBLIC_DEVNET_TOKEN_2022_APPROVE_AMOUNT_RAW=2000000000
|
||||||
|
KS_PUBLIC_DEVNET_TOKEN_2022_BURN_AMOUNT_RAW=1000000000
|
||||||
|
|
||||||
# Optional explicit environment-file selection. Relative paths use the workspace root.
|
# Optional explicit environment-file selection. Relative paths use the workspace root.
|
||||||
# Define this variable in the process environment when the selected file is not .env.
|
# Define this variable in the process environment when the selected file is not .env.
|
||||||
# KB_ENV_FILE=.env.local
|
# KS_ENV_FILE=.env.local
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# file: Cargo.toml
|
# file: Cargo.toml
|
||||||
# version: 47
|
# version: 48
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
@@ -18,7 +18,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.5.1-pre.3"
|
version = "0.5.1-pre.4"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-bot3"
|
repository = "https://git.sasedev.com/Sasedev/khadhroony-bot3"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: README.md -->
|
<!-- file: README.md -->
|
||||||
<!-- version: 21 -->
|
<!-- version: 22 -->
|
||||||
|
|
||||||
# Khadhroony Bot3
|
# Khadhroony Bot3
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ Le workspace contient onze crates :
|
|||||||
- `ks-wallet` : frontière de wallet et signataires ;
|
- `ks-wallet` : frontière de wallet et signataires ;
|
||||||
- `kb-app-demo-desktop` : application Tauri de démonstration et validation opérateur.
|
- `kb-app-demo-desktop` : application Tauri de démonstration et validation opérateur.
|
||||||
|
|
||||||
La série `0.5.x` prépare la séparation explicite entre le domaine applicatif `khadhroony-bot` et les bibliothèques généralistes `khadhroony-solana`. En `0.5.1`, les dix crates généralistes doivent migrer vers les noms `ks-*` / `ks_*`, tandis que `kb-app-demo-desktop` conserve son nom et reste une application du workspace Bot. Le workspace, le dépôt et le répertoire racine restent nommés `khadhroony-bot3` pendant cette migration et ne doivent pas être renommés avant `1.0` ou une version ultérieure explicitement dédiée. La politique de migration est définie dans [`docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md`](docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md).
|
La série `0.5.x` prépare la séparation explicite entre le domaine applicatif `khadhroony-bot` et les bibliothèques généralistes `khadhroony-solana`. Depuis `0.5.1-pre.002`, les dix crates généralistes utilisent les noms `ks-*` / `ks_*`, tandis que `kb-app-demo-desktop` conserve son nom et reste une application du workspace Bot. Le workspace, le dépôt et le répertoire racine restent nommés `khadhroony-bot3` pendant cette migration et ne doivent pas être renommés avant `1.0` ou une version ultérieure explicitement dédiée. La politique de migration est définie dans [`docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md`](docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md).
|
||||||
|
|
||||||
Références :
|
Références :
|
||||||
|
|
||||||
|
|||||||
10
ROADMAP.md
10
ROADMAP.md
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: ROADMAP.md -->
|
<!-- file: ROADMAP.md -->
|
||||||
<!-- version: 35 -->
|
<!-- version: 36 -->
|
||||||
|
|
||||||
# ROADMAP — khadhroony-bot3
|
# ROADMAP — khadhroony-bot3
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ Cadrage clôturé avant toute restructuration majeure :
|
|||||||
- audit des responsabilités et couplages de `ks-config`, `ks-logging`, `ks-wallet`, `ks-store`, `ks-pipeline-demo-scenarios` et `kb-app-demo-desktop` ;
|
- audit des responsabilités et couplages de `ks-config`, `ks-logging`, `ks-wallet`, `ks-store`, `ks-pipeline-demo-scenarios` et `kb-app-demo-desktop` ;
|
||||||
- inventaire des contrats publics, formats persistés, migrations, dépendances, scénarios et preuves de validation ;
|
- inventaire des contrats publics, formats persistés, migrations, dépendances, scénarios et preuves de validation ;
|
||||||
- confirmation du split futur entre configuration généraliste et configuration logging ;
|
- confirmation du split futur entre configuration généraliste et configuration logging ;
|
||||||
- définition de la politique de secrets et du namespace d'environnement `KS_*` ;
|
- définition de la politique de secrets et des namespaces d'environnement `KS_*` pour Khadhroony Solana et `KB_*` pour les futurs contrats réellement spécifiques au Bot ;
|
||||||
- décision de migrer les dix bibliothèques Solana généralistes vers `ks-*` / `ks_*` ;
|
- décision de migrer les dix bibliothèques Solana généralistes vers `ks-*` / `ks_*` ;
|
||||||
- décision de migrer les identités techniques généralistes `kb-lib.decoder.*`, `kb-lib.materializer.*` et `kb-lib.executor.*` vers `ks-lib-decoder.*`, `ks-lib-materializer.*` et `ks-lib-executor.*` ;
|
- décision de migrer les identités techniques généralistes `kb-lib.decoder.*`, `kb-lib.materializer.*` et `kb-lib.executor.*` vers `ks-lib-decoder.*`, `ks-lib-materializer.*` et `ks-lib-executor.*` ;
|
||||||
- confirmation que `kb-app-demo-desktop` reste côté Bot et peut héberger à terme des démos Solana généralistes et des démos spécifiques au bot ;
|
- confirmation que `kb-app-demo-desktop` reste côté Bot et peut héberger à terme des démos Solana généralistes et des démos spécifiques au bot ;
|
||||||
@@ -88,9 +88,9 @@ Cette version effectue la migration de namespace des bibliothèques Solana et re
|
|||||||
- migrer les identifiants Rust correspondants vers `ks_*`, les manifests, chemins, imports, exports, tests externes, scripts et documentation ;
|
- migrer les identifiants Rust correspondants vers `ks_*`, les manifests, chemins, imports, exports, tests externes, scripts et documentation ;
|
||||||
- conserver `kb-app-demo-desktop` comme application du domaine Bot, consommatrice des composants `ks-*` ;
|
- conserver `kb-app-demo-desktop` comme application du domaine Bot, consommatrice des composants `ks-*` ;
|
||||||
- migrer les identités runtime/persistées généralistes vers la nomenclature `ks-*`, notamment `ks-lib-decoder.*`, `ks-lib-materializer.*` et `ks-lib-executor.*`, après inventaire exhaustif des chaînes concernées ;
|
- migrer les identités runtime/persistées généralistes vers la nomenclature `ks-*`, notamment `ks-lib-decoder.*`, `ks-lib-materializer.*` et `ks-lib-executor.*`, après inventaire exhaustif des chaînes concernées ;
|
||||||
- imposer le namespace d'environnement `KS_*` pour les variables appartenant au workspace ;
|
- imposer `KS_*` aux variables possédées par les composants Solana généralistes et réserver `KB_*` aux variables réellement possédées par `kb-app-demo-desktop` ou de futures crates spécifiques au Bot ;
|
||||||
- classifier `KS_SECRET_*` comme jamais exposable, `KS_PUBLIC_*` comme publiable uniquement via une surface explicitement autorisée et les autres `KS_*` comme internes/diagnostiques ;
|
- appliquer symétriquement les classes `*_SECRET_*`, `*_PUBLIC_*` et internes aux namespaces `KS_*` et `KB_*`, avec exposition publique uniquement via une surface explicitement autorisée ;
|
||||||
- préserver la sensibilité après substitution : toute valeur composée contenant un `KS_SECRET_*` reste secrète ;
|
- préserver la sensibilité après substitution : toute valeur composée contenant un `KS_SECRET_*` ou `KB_SECRET_*` reste secrète ;
|
||||||
- séparer la configuration généraliste et la configuration logging dans des documents et schémas indépendants ;
|
- séparer la configuration généraliste et la configuration logging dans des documents et schémas indépendants ;
|
||||||
- permettre des profils logging indépendants des profils réseau/applicatifs ;
|
- permettre des profils logging indépendants des profils réseau/applicatifs ;
|
||||||
- distinguer configuration source, configuration runtime résolue et DTO publics/diagnostiques ;
|
- distinguer configuration source, configuration runtime résolue et DTO publics/diagnostiques ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: config/README.md -->
|
<!-- file: config/README.md -->
|
||||||
<!-- version: 18 -->
|
<!-- version: 19 -->
|
||||||
|
|
||||||
# Configuration locale
|
# Configuration locale
|
||||||
|
|
||||||
@@ -26,12 +26,12 @@ Ce dossier contient les exemples et le schéma de configuration JSON.
|
|||||||
`example.config.json` conserve la topologie des profils et référence les valeurs locales avec des placeholders :
|
`example.config.json` conserve la topologie des profils et référence les valeurs locales avec des placeholders :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
HELIUS_API_KEY
|
KS_SECRET_HELIUS_API_KEY
|
||||||
KB_POSTGRES_MAINNET_URL
|
KS_SECRET_POSTGRES_MAINNET_URL
|
||||||
KB_POSTGRES_DEVNET_URL
|
KS_SECRET_POSTGRES_DEVNET_URL
|
||||||
```
|
```
|
||||||
|
|
||||||
`KB_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 `KB_POSTGRES_DEVNET_URL`; les profils `mainnet_research` et `mainnet` utilisent `KB_POSTGRES_MAINNET_URL`. Les trois bases doivent être distinctes.
|
`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.
|
||||||
|
|
||||||
Le fichier réel `.env` reste local et ignoré par Git. `.env.example` est le seul modèle dotenv versionné.
|
Le fichier réel `.env` reste local et ignoré par Git. `.env.example` est le seul modèle dotenv versionné.
|
||||||
|
|
||||||
@@ -101,4 +101,3 @@ http_transactions:
|
|||||||
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 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.
|
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.
|
||||||
|
|
||||||
|
|||||||
@@ -1195,7 +1195,7 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"backend": "postgres",
|
"backend": "postgres",
|
||||||
"postgres": {
|
"postgres": {
|
||||||
"url": "${KB_POSTGRES_DEVNET_URL}",
|
"url": "${KS_SECRET_POSTGRES_DEVNET_URL}",
|
||||||
"max_connections": 8,
|
"max_connections": 8,
|
||||||
"connect_timeout_ms": 5000,
|
"connect_timeout_ms": 5000,
|
||||||
"auto_initialize_schema": true
|
"auto_initialize_schema": true
|
||||||
@@ -2613,7 +2613,7 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"backend": "postgres",
|
"backend": "postgres",
|
||||||
"postgres": {
|
"postgres": {
|
||||||
"url": "${KB_POSTGRES_MAINNET_URL}",
|
"url": "${KS_SECRET_POSTGRES_MAINNET_URL}",
|
||||||
"max_connections": 16,
|
"max_connections": 16,
|
||||||
"connect_timeout_ms": 5000,
|
"connect_timeout_ms": 5000,
|
||||||
"auto_initialize_schema": true
|
"auto_initialize_schema": true
|
||||||
@@ -2764,7 +2764,7 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"provider": "helius",
|
"provider": "helius",
|
||||||
"cluster": "mainnet-beta",
|
"cluster": "mainnet-beta",
|
||||||
"url": "https://mainnet.helius-rpc.com/?api-key=${HELIUS_API_KEY}",
|
"url": "https://mainnet.helius-rpc.com/?api-key=${KS_SECRET_HELIUS_API_KEY}",
|
||||||
"connect_timeout_ms": 4000,
|
"connect_timeout_ms": 4000,
|
||||||
"request_timeout_ms": 10000,
|
"request_timeout_ms": 10000,
|
||||||
"max_idle_connections_per_host": 8,
|
"max_idle_connections_per_host": 8,
|
||||||
@@ -2924,7 +2924,7 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"provider": "helius",
|
"provider": "helius",
|
||||||
"cluster": "mainnet-beta",
|
"cluster": "mainnet-beta",
|
||||||
"url": "wss://mainnet.helius-rpc.com/?api-key=${HELIUS_API_KEY}",
|
"url": "wss://mainnet.helius-rpc.com/?api-key=${KS_SECRET_HELIUS_API_KEY}",
|
||||||
"connect_timeout_ms": 5000,
|
"connect_timeout_ms": 5000,
|
||||||
"request_timeout_ms": 10000,
|
"request_timeout_ms": 10000,
|
||||||
"unsubscribe_timeout_ms": 1500,
|
"unsubscribe_timeout_ms": 1500,
|
||||||
@@ -4231,7 +4231,7 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"backend": "postgres",
|
"backend": "postgres",
|
||||||
"postgres": {
|
"postgres": {
|
||||||
"url": "${KB_POSTGRES_MAINNET_URL}",
|
"url": "${KS_SECRET_POSTGRES_MAINNET_URL}",
|
||||||
"max_connections": 16,
|
"max_connections": 16,
|
||||||
"connect_timeout_ms": 5000,
|
"connect_timeout_ms": 5000,
|
||||||
"auto_initialize_schema": true
|
"auto_initialize_schema": true
|
||||||
@@ -4382,7 +4382,7 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"provider": "helius",
|
"provider": "helius",
|
||||||
"cluster": "mainnet-beta",
|
"cluster": "mainnet-beta",
|
||||||
"url": "https://mainnet.helius-rpc.com/?api-key=${HELIUS_API_KEY}",
|
"url": "https://mainnet.helius-rpc.com/?api-key=${KS_SECRET_HELIUS_API_KEY}",
|
||||||
"connect_timeout_ms": 4000,
|
"connect_timeout_ms": 4000,
|
||||||
"request_timeout_ms": 10000,
|
"request_timeout_ms": 10000,
|
||||||
"max_idle_connections_per_host": 8,
|
"max_idle_connections_per_host": 8,
|
||||||
@@ -4542,7 +4542,7 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"provider": "helius",
|
"provider": "helius",
|
||||||
"cluster": "mainnet-beta",
|
"cluster": "mainnet-beta",
|
||||||
"url": "wss://mainnet.helius-rpc.com/?api-key=${HELIUS_API_KEY}",
|
"url": "wss://mainnet.helius-rpc.com/?api-key=${KS_SECRET_HELIUS_API_KEY}",
|
||||||
"connect_timeout_ms": 5000,
|
"connect_timeout_ms": 5000,
|
||||||
"request_timeout_ms": 10000,
|
"request_timeout_ms": 10000,
|
||||||
"unsubscribe_timeout_ms": 1500,
|
"unsubscribe_timeout_ms": 1500,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/DEVNET_EXECUTION_GUIDE.md -->
|
<!-- file: docs/DEVNET_EXECUTION_GUIDE.md -->
|
||||||
<!-- version: 25 -->
|
<!-- version: 26 -->
|
||||||
|
|
||||||
# Guide d’exécution Devnet
|
# Guide d’exécution Devnet
|
||||||
|
|
||||||
@@ -21,8 +21,8 @@ Les commandes réutilisables sont centralisées en section 4. Chaque scénario r
|
|||||||
|
|
||||||
## 2. Préconditions
|
## 2. Préconditions
|
||||||
|
|
||||||
- `.env` contient `KB_POSTGRES_DEVNET_URL` et les secrets de transport requis ;
|
- `.env` contient `KS_SECRET_POSTGRES_DEVNET_URL` et les secrets de transport requis ;
|
||||||
- `KB_POSTGRES_DEVNET_URL`, `KB_POSTGRES_MAINNET_URL` et `KB_POSTGRES_TEST_URL` désignent des bases distinctes ;
|
- `KS_SECRET_POSTGRES_DEVNET_URL`, `KS_SECRET_POSTGRES_MAINNET_URL` et `KS_SECRET_POSTGRES_TEST_URL` désignent des bases distinctes ;
|
||||||
- le profil sélectionné est Devnet et autorise explicitement l’envoi Devnet ;
|
- le profil sélectionné est Devnet et autorise explicitement l’envoi Devnet ;
|
||||||
- l’envoi Mainnet reste désactivé ;
|
- l’envoi Mainnet reste désactivé ;
|
||||||
- les plafonds de frais, de dépense et de rent sont contrôlés ;
|
- les plafonds de frais, de dépense et de rent sont contrôlés ;
|
||||||
@@ -44,7 +44,7 @@ Ce terminal reste occupé par `cargo tauri dev` pendant toute la campagne. Il af
|
|||||||
|
|
||||||
Ce terminal reste disponible pour les commandes Solana, PostgreSQL, balances, confirmations et captures avec `tee`.
|
Ce terminal reste disponible pour les commandes Solana, PostgreSQL, balances, confirmations et captures avec `tee`.
|
||||||
|
|
||||||
Les commandes `C01` à `C05` doivent être exécutées dans le terminal B. Le terminal A doit exécuter `T01`, puis rester ouvert. Avant chaque scénario, le terminal B doit définir `KB_DEVNET_SCENARIO` avant d’appeler `C06`.
|
Les commandes `C01` à `C05` doivent être exécutées dans le terminal B. Le terminal A doit exécuter `T01`, puis rester ouvert. Avant chaque scénario, le terminal B doit définir `KS_DEVNET_SCENARIO` avant d’appeler `C06`.
|
||||||
|
|
||||||
## 4. Commandes communes
|
## 4. Commandes communes
|
||||||
|
|
||||||
@@ -100,13 +100,13 @@ Arrêter avec `Ctrl+C`, puis relancer `T01`.
|
|||||||
### C01 — Initialiser l’environnement de validation
|
### C01 — Initialiser l’environnement de validation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd ~/Projects/khadhroony-bot3 && set -o pipefail && export KB_DEVNET_PROFILE="local_devnet" && export KB_DEVNET_RPC_URL="https://api.devnet.solana.com" && export KB_DEVNET_VALIDATION_DIR="/tmp/devnet-validation/current" && export KB_DEVNET_WALLET="$PWD/wallets/temporary/local_devnet/local-devnet-operator.json" && mkdir -p "$KB_DEVNET_VALIDATION_DIR" && printf 'Profil : %s\n' "$KB_DEVNET_PROFILE" && printf 'RPC Devnet : %s\n' "$KB_DEVNET_RPC_URL" && printf 'Preuves : %s\n' "$KB_DEVNET_VALIDATION_DIR" && printf 'Wallet : %s\n' "$KB_DEVNET_WALLET";
|
cd ~/Projects/khadhroony-bot3 && set -o pipefail && export KS_DEVNET_PROFILE="local_devnet" && export KS_DEVNET_RPC_URL="https://api.devnet.solana.com" && export KS_DEVNET_VALIDATION_DIR="/tmp/devnet-validation/current" && export KS_DEVNET_WALLET="$PWD/wallets/temporary/local_devnet/local-devnet-operator.json" && mkdir -p "$KS_DEVNET_VALIDATION_DIR" && printf 'Profil : %s\n' "$KS_DEVNET_PROFILE" && printf 'RPC Devnet : %s\n' "$KS_DEVNET_RPC_URL" && printf 'Preuves : %s\n' "$KS_DEVNET_VALIDATION_DIR" && printf 'Wallet : %s\n' "$KS_DEVNET_WALLET";
|
||||||
```
|
```
|
||||||
|
|
||||||
### C02 — Capturer les versions CLI
|
### C02 — Capturer les versions CLI
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
command -v solana && command -v solana-keygen && command -v spl-token && { date --iso-8601=seconds; solana --version; solana-keygen --version; spl-token --version; } | tee "$KB_DEVNET_VALIDATION_DIR/00-cli-versions.txt";
|
command -v solana && command -v solana-keygen && command -v spl-token && { date --iso-8601=seconds; solana --version; solana-keygen --version; spl-token --version; } | tee "$KS_DEVNET_VALIDATION_DIR/00-cli-versions.txt";
|
||||||
```
|
```
|
||||||
|
|
||||||
Chaque campagne doit capturer les versions exactes des outils externes qu’elle utilise. Les fixtures Rust natives ne doivent pas dépendre implicitement de la configuration globale d’une CLI.
|
Chaque campagne doit capturer les versions exactes des outils externes qu’elle utilise. Les fixtures Rust natives ne doivent pas dépendre implicitement de la configuration globale d’une CLI.
|
||||||
@@ -114,7 +114,7 @@ Chaque campagne doit capturer les versions exactes des outils externes qu’elle
|
|||||||
### C03 — Vérifier l’identité du réseau
|
### C03 — Vérifier l’identité du réseau
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
solana config set --url "$KB_DEVNET_RPC_URL" && { date --iso-8601=seconds; solana config get; solana cluster-version --url "$KB_DEVNET_RPC_URL"; solana genesis-hash --url "$KB_DEVNET_RPC_URL"; solana epoch-info --url "$KB_DEVNET_RPC_URL"; } | tee "$KB_DEVNET_VALIDATION_DIR/01-devnet-network.txt";
|
solana config set --url "$KS_DEVNET_RPC_URL" && { date --iso-8601=seconds; solana config get; solana cluster-version --url "$KS_DEVNET_RPC_URL"; solana genesis-hash --url "$KS_DEVNET_RPC_URL"; solana epoch-info --url "$KS_DEVNET_RPC_URL"; } | tee "$KS_DEVNET_VALIDATION_DIR/01-devnet-network.txt";
|
||||||
```
|
```
|
||||||
|
|
||||||
Le genesis hash Devnet attendu est :
|
Le genesis hash Devnet attendu est :
|
||||||
@@ -126,37 +126,37 @@ EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG
|
|||||||
### C04 — Vérifier le wallet opérateur
|
### C04 — Vérifier le wallet opérateur
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
test -f "$KB_DEVNET_WALLET" && chmod 600 "$KB_DEVNET_WALLET" && export KB_DEVNET_WALLET_PUBKEY="$(solana-keygen pubkey "$KB_DEVNET_WALLET")" && { date --iso-8601=seconds; printf 'wallet_path=%s\n' "$KB_DEVNET_WALLET"; printf 'wallet_pubkey=%s\n' "$KB_DEVNET_WALLET_PUBKEY"; solana balance "$KB_DEVNET_WALLET_PUBKEY" --url "$KB_DEVNET_RPC_URL" --commitment confirmed; } | tee "$KB_DEVNET_VALIDATION_DIR/02-wallet.txt"
|
test -f "$KS_DEVNET_WALLET" && chmod 600 "$KS_DEVNET_WALLET" && export KS_PUBLIC_DEVNET_WALLET_ADDRESS="$(solana-keygen pubkey "$KS_DEVNET_WALLET")" && { date --iso-8601=seconds; printf 'wallet_path=%s\n' "$KS_DEVNET_WALLET"; printf 'wallet_pubkey=%s\n' "$KS_PUBLIC_DEVNET_WALLET_ADDRESS"; solana balance "$KS_PUBLIC_DEVNET_WALLET_ADDRESS" --url "$KS_DEVNET_RPC_URL" --commitment confirmed; } | tee "$KS_DEVNET_VALIDATION_DIR/02-wallet.txt"
|
||||||
```
|
```
|
||||||
|
|
||||||
### C05 — Recréer la base Devnet
|
### C05 — Recréer la base Devnet
|
||||||
|
|
||||||
Cette commande est destructive. Elle ne doit viser que `KB_POSTGRES_DEVNET_URL`. Elle supprime toutes les données et tous les objets du schéma `public`, puis laisse l’application recréer son schéma lors de l’ouverture d’une fenêtre Devnet.
|
Cette commande est destructive. Elle ne doit viser que `KS_SECRET_POSTGRES_DEVNET_URL`. Elle supprime toutes les données et tous les objets du schéma `public`, puis laisse l’application recréer son schéma lors de l’ouverture d’une fenêtre Devnet.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
test -n "$KB_POSTGRES_DEVNET_URL" && printf '%s\n' "$KB_POSTGRES_DEVNET_URL" && export KB_CONFIRM_DEVNET_DATABASE_RESET="YES_RESET_SOLANA_DEVNET" && test "$KB_CONFIRM_DEVNET_DATABASE_RESET" = "YES_RESET_SOLANA_DEVNET" && psql "$KB_POSTGRES_DEVNET_URL" -v ON_ERROR_STOP=1 -c 'DROP SCHEMA public CASCADE; CREATE SCHEMA public;'
|
test -n "$KS_SECRET_POSTGRES_DEVNET_URL" && printf 'database_url=<configured>\n' && export KS_CONFIRM_DEVNET_DATABASE_RESET="YES_RESET_SOLANA_DEVNET" && test "$KS_CONFIRM_DEVNET_DATABASE_RESET" = "YES_RESET_SOLANA_DEVNET" && psql "$KS_SECRET_POSTGRES_DEVNET_URL" -v ON_ERROR_STOP=1 -c 'DROP SCHEMA public CASCADE; CREATE SCHEMA public;'
|
||||||
```
|
```
|
||||||
|
|
||||||
Après ouverture d’une fenêtre Devnet, contrôler les tables :
|
Après ouverture d’une fenêtre Devnet, contrôler les tables :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
psql "$KB_POSTGRES_DEVNET_URL" -v ON_ERROR_STOP=1 -c "SELECT schemaname, tablename FROM pg_tables WHERE schemaname = 'public' ORDER BY tablename;" | tee "$KB_DEVNET_VALIDATION_DIR/03-devnet-schema.txt"
|
psql "$KS_SECRET_POSTGRES_DEVNET_URL" -v ON_ERROR_STOP=1 -c "SELECT schemaname, tablename FROM pg_tables WHERE schemaname = 'public' ORDER BY tablename;" | tee "$KS_DEVNET_VALIDATION_DIR/03-devnet-schema.txt"
|
||||||
```
|
```
|
||||||
|
|
||||||
### C06 — Capturer le solde avant scénario
|
### C06 — Capturer le solde avant scénario
|
||||||
|
|
||||||
Définir `KB_DEVNET_SCENARIO` avant l’appel.
|
Définir `KS_DEVNET_SCENARIO` avant l’appel.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
test -n "${KB_DEVNET_SCENARIO:-}" && test -n "${KB_DEVNET_WALLET_PUBKEY:-}" && test -n "${KB_DEVNET_RPC_URL:-}" && test -n "${KB_DEVNET_VALIDATION_DIR:-}" && { date --iso-8601=seconds; printf 'scenario=%s\nwallet=%s\n' "$KB_DEVNET_SCENARIO" "$KB_DEVNET_WALLET_PUBKEY"; solana balance "$KB_DEVNET_WALLET_PUBKEY" --url "$KB_DEVNET_RPC_URL" --commitment confirmed; } | tee "$KB_DEVNET_VALIDATION_DIR/${KB_DEVNET_SCENARIO}-wallet-before.txt"
|
test -n "${KS_DEVNET_SCENARIO:-}" && test -n "${KS_PUBLIC_DEVNET_WALLET_ADDRESS:-}" && test -n "${KS_DEVNET_RPC_URL:-}" && test -n "${KS_DEVNET_VALIDATION_DIR:-}" && { date --iso-8601=seconds; printf 'scenario=%s\nwallet=%s\n' "$KS_DEVNET_SCENARIO" "$KS_PUBLIC_DEVNET_WALLET_ADDRESS"; solana balance "$KS_PUBLIC_DEVNET_WALLET_ADDRESS" --url "$KS_DEVNET_RPC_URL" --commitment confirmed; } | tee "$KS_DEVNET_VALIDATION_DIR/${KS_DEVNET_SCENARIO}-wallet-before.txt"
|
||||||
```
|
```
|
||||||
|
|
||||||
### C07 — Confirmer une signature et capturer le solde après scénario
|
### C07 — Confirmer une signature et capturer le solde après scénario
|
||||||
|
|
||||||
Définir `KB_DEVNET_SCENARIO` et `KB_DEVNET_SIGNATURE` avant l’appel.
|
Définir `KS_DEVNET_SCENARIO` et `KS_DEVNET_SIGNATURE` avant l’appel.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
test -n "${KB_DEVNET_SCENARIO:-}" && test -n "${KB_DEVNET_SIGNATURE:-}" && test -n "${KB_DEVNET_WALLET_PUBKEY:-}" && test -n "${KB_DEVNET_RPC_URL:-}" && test -n "${KB_DEVNET_VALIDATION_DIR:-}" && { date --iso-8601=seconds; printf 'scenario=%s\nsignature=%s\n' "$KB_DEVNET_SCENARIO" "$KB_DEVNET_SIGNATURE"; solana confirm "$KB_DEVNET_SIGNATURE" --url "$KB_DEVNET_RPC_URL" --commitment finalized --verbose; solana balance "$KB_DEVNET_WALLET_PUBKEY" --url "$KB_DEVNET_RPC_URL" --commitment confirmed; } | tee "$KB_DEVNET_VALIDATION_DIR/${KB_DEVNET_SCENARIO}-confirmation.txt"
|
test -n "${KS_DEVNET_SCENARIO:-}" && test -n "${KS_DEVNET_SIGNATURE:-}" && test -n "${KS_PUBLIC_DEVNET_WALLET_ADDRESS:-}" && test -n "${KS_DEVNET_RPC_URL:-}" && test -n "${KS_DEVNET_VALIDATION_DIR:-}" && { date --iso-8601=seconds; printf 'scenario=%s\nsignature=%s\n' "$KS_DEVNET_SCENARIO" "$KS_DEVNET_SIGNATURE"; solana confirm "$KS_DEVNET_SIGNATURE" --url "$KS_DEVNET_RPC_URL" --commitment finalized --verbose; solana balance "$KS_PUBLIC_DEVNET_WALLET_ADDRESS" --url "$KS_DEVNET_RPC_URL" --commitment confirmed; } | tee "$KS_DEVNET_VALIDATION_DIR/${KS_DEVNET_SCENARIO}-confirmation.txt"
|
||||||
```
|
```
|
||||||
|
|
||||||
### C08 — Préparer un mint SPL Token classique pour ATA
|
### C08 — Préparer un mint SPL Token classique pour ATA
|
||||||
@@ -168,11 +168,11 @@ L’option `--silent` est obligatoire afin que la phrase de récupération ne so
|
|||||||
La commande est idempotente au niveau du guide : si le compte du mint existe déjà sur Devnet, elle le réutilise.
|
La commande est idempotente au niveau du guide : si le compte du mint existe déjà sur Devnet, elle le réutilise.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_SPL_TOKEN_PROGRAM_ID="TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" && export KB_DEVNET_CLASSIC_MINT_KEYPAIR="$PWD/wallets/temporary/local_devnet/mints/ata-classic-mint.json" && mkdir -p "$(dirname "$KB_DEVNET_CLASSIC_MINT_KEYPAIR")" && { test -f "$KB_DEVNET_CLASSIC_MINT_KEYPAIR" || solana-keygen new --no-bip39-passphrase --force --silent --outfile "$KB_DEVNET_CLASSIC_MINT_KEYPAIR"; }
|
export KS_PUBLIC_SPL_TOKEN_PROGRAM_ID="TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" && export KS_DEVNET_CLASSIC_MINT_KEYPAIR="$PWD/wallets/temporary/local_devnet/mints/ata-classic-mint.json" && mkdir -p "$(dirname "$KS_DEVNET_CLASSIC_MINT_KEYPAIR")" && { test -f "$KS_DEVNET_CLASSIC_MINT_KEYPAIR" || solana-keygen new --no-bip39-passphrase --force --silent --outfile "$KS_DEVNET_CLASSIC_MINT_KEYPAIR"; }
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_CLASSIC_MINT="$(solana-keygen pubkey "$KB_DEVNET_CLASSIC_MINT_KEYPAIR")" && { solana account "$KB_DEVNET_CLASSIC_MINT" --url "$KB_DEVNET_RPC_URL" --output json >/dev/null 2>&1 || spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" create-token "$KB_DEVNET_CLASSIC_MINT_KEYPAIR" --decimals 9; } && printf 'classic_mint=%s\n' "$KB_DEVNET_CLASSIC_MINT" | tee "$KB_DEVNET_VALIDATION_DIR/30a-spl-ata-classic-mint.txt"
|
export KS_DEVNET_CLASSIC_MINT="$(solana-keygen pubkey "$KS_DEVNET_CLASSIC_MINT_KEYPAIR")" && { solana account "$KS_DEVNET_CLASSIC_MINT" --url "$KS_DEVNET_RPC_URL" --output json >/dev/null 2>&1 || spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_PROGRAM_ID" create-token "$KS_DEVNET_CLASSIC_MINT_KEYPAIR" --decimals 9; } && printf 'classic_mint=%s\n' "$KS_DEVNET_CLASSIC_MINT" | tee "$KS_DEVNET_VALIDATION_DIR/30a-spl-ata-classic-mint.txt"
|
||||||
```
|
```
|
||||||
|
|
||||||
### C09 — Préparer un mint Token-2022 pour ATA
|
### C09 — Préparer un mint Token-2022 pour ATA
|
||||||
@@ -180,11 +180,11 @@ export KB_DEVNET_CLASSIC_MINT="$(solana-keygen pubkey "$KB_DEVNET_CLASSIC_MINT_K
|
|||||||
Cette commande crée uniquement un mint Token-2022 de test persistant, sans extension supplémentaire. Elle ne crée aucun ATA.
|
Cette commande crée uniquement un mint Token-2022 de test persistant, sans extension supplémentaire. Elle ne crée aucun ATA.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_SPL_TOKEN_2022_PROGRAM_ID="TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" && export KB_DEVNET_TOKEN_2022_MINT_KEYPAIR="$PWD/wallets/temporary/local_devnet/mints/ata-token-2022-mint.json" && mkdir -p "$(dirname "$KB_DEVNET_TOKEN_2022_MINT_KEYPAIR")" && { test -f "$KB_DEVNET_TOKEN_2022_MINT_KEYPAIR" || solana-keygen new --no-bip39-passphrase --force --silent --outfile "$KB_DEVNET_TOKEN_2022_MINT_KEYPAIR"; }
|
export KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID="TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" && export KS_DEVNET_TOKEN_2022_MINT_KEYPAIR="$PWD/wallets/temporary/local_devnet/mints/ata-token-2022-mint.json" && mkdir -p "$(dirname "$KS_DEVNET_TOKEN_2022_MINT_KEYPAIR")" && { test -f "$KS_DEVNET_TOKEN_2022_MINT_KEYPAIR" || solana-keygen new --no-bip39-passphrase --force --silent --outfile "$KS_DEVNET_TOKEN_2022_MINT_KEYPAIR"; }
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_TOKEN_2022_MINT="$(solana-keygen pubkey "$KB_DEVNET_TOKEN_2022_MINT_KEYPAIR")" && { solana account "$KB_DEVNET_TOKEN_2022_MINT" --url "$KB_DEVNET_RPC_URL" --output json >/dev/null 2>&1 || spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_2022_PROGRAM_ID" create-token "$KB_DEVNET_TOKEN_2022_MINT_KEYPAIR" --decimals 9; } && printf 'token_2022_mint=%s\n' "$KB_DEVNET_TOKEN_2022_MINT" | tee "$KB_DEVNET_VALIDATION_DIR/30b-spl-ata-token-2022-mint.txt"
|
export KS_PUBLIC_DEVNET_TOKEN_2022_MINT="$(solana-keygen pubkey "$KS_DEVNET_TOKEN_2022_MINT_KEYPAIR")" && { solana account "$KS_PUBLIC_DEVNET_TOKEN_2022_MINT" --url "$KS_DEVNET_RPC_URL" --output json >/dev/null 2>&1 || spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID" create-token "$KS_DEVNET_TOKEN_2022_MINT_KEYPAIR" --decimals 9; } && printf 'token_2022_mint=%s\n' "$KS_PUBLIC_DEVNET_TOKEN_2022_MINT" | tee "$KS_DEVNET_VALIDATION_DIR/30b-spl-ata-token-2022-mint.txt"
|
||||||
```
|
```
|
||||||
|
|
||||||
### C10 — Préparer les comptes du scénario SPL Token classique
|
### C10 — Préparer les comptes du scénario SPL Token classique
|
||||||
@@ -201,37 +201,37 @@ Cette préparation réutilise le mint créé par `C08` et l’ATA classique cré
|
|||||||
1. Dériver l’ATA source avec la syntaxe exigée par `spl-token-cli 5.5.0` :
|
1. Dériver l’ATA source avec la syntaxe exigée par `spl-token-cli 5.5.0` :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_CLASSIC_SOURCE_ATA="$(spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" address --verbose --token "$KB_DEVNET_CLASSIC_MINT" --owner "$KB_DEVNET_WALLET_PUBKEY" | awk -F': ' '/Associated token address/ {print $2}')" && test -n "$KB_DEVNET_CLASSIC_SOURCE_ATA" && printf 'source_ata=%s\n' "$KB_DEVNET_CLASSIC_SOURCE_ATA"
|
export KS_DEVNET_CLASSIC_SOURCE_ATA="$(spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_PROGRAM_ID" address --verbose --token "$KS_DEVNET_CLASSIC_MINT" --owner "$KS_PUBLIC_DEVNET_WALLET_ADDRESS" | awk -F': ' '/Associated token address/ {print $2}')" && test -n "$KS_DEVNET_CLASSIC_SOURCE_ATA" && printf 'source_ata=%s\n' "$KS_DEVNET_CLASSIC_SOURCE_ATA"
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Préparer un owner destinataire persistant :
|
2. Préparer un owner destinataire persistant :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_CLASSIC_RECIPIENT_KEYPAIR="$PWD/wallets/temporary/local_devnet/recipients/spl-token-transfer-recipient.json" && mkdir -p "$(dirname "$KB_DEVNET_CLASSIC_RECIPIENT_KEYPAIR")" && { test -f "$KB_DEVNET_CLASSIC_RECIPIENT_KEYPAIR" || solana-keygen new --no-bip39-passphrase --force --silent --outfile "$KB_DEVNET_CLASSIC_RECIPIENT_KEYPAIR"; } && export KB_DEVNET_CLASSIC_RECIPIENT="$(solana-keygen pubkey "$KB_DEVNET_CLASSIC_RECIPIENT_KEYPAIR")"
|
export KS_DEVNET_CLASSIC_RECIPIENT_KEYPAIR="$PWD/wallets/temporary/local_devnet/recipients/spl-token-transfer-recipient.json" && mkdir -p "$(dirname "$KS_DEVNET_CLASSIC_RECIPIENT_KEYPAIR")" && { test -f "$KS_DEVNET_CLASSIC_RECIPIENT_KEYPAIR" || solana-keygen new --no-bip39-passphrase --force --silent --outfile "$KS_DEVNET_CLASSIC_RECIPIENT_KEYPAIR"; } && export KS_DEVNET_CLASSIC_RECIPIENT="$(solana-keygen pubkey "$KS_DEVNET_CLASSIC_RECIPIENT_KEYPAIR")"
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Dériver puis créer l’ATA destination si elle n’existe pas :
|
3. Dériver puis créer l’ATA destination si elle n’existe pas :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_CLASSIC_DESTINATION_ATA="$(spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" address --verbose --token "$KB_DEVNET_CLASSIC_MINT" --owner "$KB_DEVNET_CLASSIC_RECIPIENT" | awk -F': ' '/Associated token address/ {print $2}')" && test -n "$KB_DEVNET_CLASSIC_DESTINATION_ATA" && { solana account "$KB_DEVNET_CLASSIC_DESTINATION_ATA" --url "$KB_DEVNET_RPC_URL" --output json >/dev/null 2>&1 || spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" create-account "$KB_DEVNET_CLASSIC_MINT" --owner "$KB_DEVNET_CLASSIC_RECIPIENT" --fee-payer "$KB_DEVNET_WALLET"; }
|
export KS_DEVNET_CLASSIC_DESTINATION_ATA="$(spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_PROGRAM_ID" address --verbose --token "$KS_DEVNET_CLASSIC_MINT" --owner "$KS_DEVNET_CLASSIC_RECIPIENT" | awk -F': ' '/Associated token address/ {print $2}')" && test -n "$KS_DEVNET_CLASSIC_DESTINATION_ATA" && { solana account "$KS_DEVNET_CLASSIC_DESTINATION_ATA" --url "$KS_DEVNET_RPC_URL" --output json >/dev/null 2>&1 || spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_PROGRAM_ID" create-account "$KS_DEVNET_CLASSIC_MINT" --owner "$KS_DEVNET_CLASSIC_RECIPIENT" --fee-payer "$KS_DEVNET_WALLET"; }
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Créditer le compte source. Cette commande ajoute `10` tokens à chaque exécution ; ne la relancer que si le solde source est insuffisant :
|
4. Créditer le compte source. Cette commande ajoute `10` tokens à chaque exécution ; ne la relancer que si le solde source est insuffisant :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" mint "$KB_DEVNET_CLASSIC_MINT" 10 "$KB_DEVNET_CLASSIC_SOURCE_ATA" --owner "$KB_DEVNET_WALLET" --fee-payer "$KB_DEVNET_WALLET"
|
spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_PROGRAM_ID" mint "$KS_DEVNET_CLASSIC_MINT" 10 "$KS_DEVNET_CLASSIC_SOURCE_ATA" --owner "$KS_DEVNET_WALLET" --fee-payer "$KS_DEVNET_WALLET"
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Afficher les comptes par leur adresse. Avec cette version du CLI, utiliser `display` plutôt que `account-info <adresse>`, car l’argument positionnel de `account-info` est interprété comme un mint :
|
5. Afficher les comptes par leur adresse. Avec cette version du CLI, utiliser `display` plutôt que `account-info <adresse>`, car l’argument positionnel de `account-info` est interprété comme un mint :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" display "$KB_DEVNET_CLASSIC_SOURCE_ATA" && spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" display "$KB_DEVNET_CLASSIC_DESTINATION_ATA"
|
spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_PROGRAM_ID" display "$KS_DEVNET_CLASSIC_SOURCE_ATA" && spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_PROGRAM_ID" display "$KS_DEVNET_CLASSIC_DESTINATION_ATA"
|
||||||
```
|
```
|
||||||
|
|
||||||
6. Capturer la fixture :
|
6. Capturer la fixture :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
{ printf 'mint=%s\n' "$KB_DEVNET_CLASSIC_MINT"; printf 'source=%s\n' "$KB_DEVNET_CLASSIC_SOURCE_ATA"; printf 'destination=%s\n' "$KB_DEVNET_CLASSIC_DESTINATION_ATA"; printf 'authority=%s\n' "$KB_DEVNET_WALLET_PUBKEY"; printf 'amount_raw=1000000000\n'; printf 'decimals=9\n'; } | tee "$KB_DEVNET_VALIDATION_DIR/40-spl-token-fixture.txt"
|
{ printf 'mint=%s\n' "$KS_DEVNET_CLASSIC_MINT"; printf 'source=%s\n' "$KS_DEVNET_CLASSIC_SOURCE_ATA"; printf 'destination=%s\n' "$KS_DEVNET_CLASSIC_DESTINATION_ATA"; printf 'authority=%s\n' "$KS_PUBLIC_DEVNET_WALLET_ADDRESS"; printf 'amount_raw=1000000000\n'; printf 'decimals=9\n'; } | tee "$KS_DEVNET_VALIDATION_DIR/40-spl-token-fixture.txt"
|
||||||
```
|
```
|
||||||
|
|
||||||
La création du compte destination par CLI est acceptable ici : `S03A` et `S03B` ont déjà validé l’executor ATA. `S04` doit isoler et valider l’executor SPL Token `TransferChecked`.
|
La création du compte destination par CLI est acceptable ici : `S03A` et `S03B` ont déjà validé l’executor ATA. `S04` doit isoler et valider l’executor SPL Token `TransferChecked`.
|
||||||
@@ -241,10 +241,10 @@ La création du compte destination par CLI est acceptable ici : `S03A` et `S03B`
|
|||||||
Le workspace fournit une commande idempotente qui prépare les comptes publics requis par les huit scénarios Token-2022 :
|
Le workspace fournit une commande idempotente qui prépare les comptes publics requis par les huit scénarios Token-2022 :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo run -p ks-pipeline-demo-scenarios --bin ks-pipeline-demo-scenarios-cli -- prepare-token-2022-fixture --rpc-url "$KB_DEVNET_RPC_URL" --wallet "$KB_DEVNET_WALLET" --wallet-dir "$PWD/wallets/temporary/local_devnet" --decimals 9 | tee "$KB_DEVNET_VALIDATION_DIR/50-spl-token-2022-fixture-preparation.json"
|
cargo run -p ks-pipeline-demo-scenarios --bin ks-pipeline-demo-scenarios-cli -- prepare-token-2022-fixture --rpc-url "$KS_DEVNET_RPC_URL" --wallet "$KS_DEVNET_WALLET" --wallet-dir "$PWD/wallets/temporary/local_devnet" --decimals 9 | tee "$KS_DEVNET_VALIDATION_DIR/50-spl-token-2022-fixture-preparation.json"
|
||||||
```
|
```
|
||||||
|
|
||||||
Lorsque `--rpc-url` et `--wallet` sont omis, la commande utilise respectivement `KB_DEVNET_RPC_URL` et `KB_DEVNET_WALLET`. Lorsque `--wallet-dir` est omis, elle utilise le répertoire parent du wallet.
|
Lorsque `--rpc-url` et `--wallet` sont omis, la commande utilise respectivement `KS_DEVNET_RPC_URL` et `KS_DEVNET_WALLET`. Lorsque `--wallet-dir` est omis, elle utilise le répertoire parent du wallet.
|
||||||
|
|
||||||
La commande :
|
La commande :
|
||||||
|
|
||||||
@@ -270,35 +270,35 @@ wallets/temporary/local_devnet/spl_token_2022_validation/fixture.env
|
|||||||
Elle définit :
|
Elle définit :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
TOKEN_2022_PROGRAM
|
KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID
|
||||||
TOKEN_2022_MINT
|
KS_PUBLIC_DEVNET_TOKEN_2022_MINT
|
||||||
TOKEN_2022_SOURCE
|
KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE
|
||||||
TOKEN_2022_DESTINATION
|
KS_PUBLIC_DEVNET_TOKEN_2022_DESTINATION
|
||||||
TOKEN_2022_CLOSE_ACCOUNT
|
KS_PUBLIC_DEVNET_TOKEN_2022_CLOSE_ACCOUNT
|
||||||
TOKEN_2022_DELEGATE
|
KS_PUBLIC_DEVNET_TOKEN_2022_DELEGATE
|
||||||
TOKEN_2022_AUTHORITY
|
KS_PUBLIC_DEVNET_TOKEN_2022_AUTHORITY
|
||||||
TOKEN_2022_FREEZE_AUTHORITY
|
KS_PUBLIC_DEVNET_TOKEN_2022_FREEZE_AUTHORITY
|
||||||
TOKEN_2022_DECIMALS
|
KS_PUBLIC_DEVNET_TOKEN_2022_DECIMALS
|
||||||
TOKEN_2022_MINT_AMOUNT_RAW
|
KS_PUBLIC_DEVNET_TOKEN_2022_MINT_AMOUNT_RAW
|
||||||
TOKEN_2022_TRANSFER_AMOUNT_RAW
|
KS_PUBLIC_DEVNET_TOKEN_2022_TRANSFER_AMOUNT_RAW
|
||||||
TOKEN_2022_APPROVE_AMOUNT_RAW
|
KS_PUBLIC_DEVNET_TOKEN_2022_APPROVE_AMOUNT_RAW
|
||||||
TOKEN_2022_BURN_AMOUNT_RAW
|
KS_PUBLIC_DEVNET_TOKEN_2022_BURN_AMOUNT_RAW
|
||||||
KB_DEVNET_WALLET_ADDRESS
|
KS_PUBLIC_DEVNET_WALLET_ADDRESS
|
||||||
```
|
```
|
||||||
|
|
||||||
Vérifier puis charger uniquement les valeurs publiques dans le terminal B :
|
Vérifier puis charger uniquement les valeurs publiques dans le terminal B :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_TOKEN_2022_FIXTURE="$PWD/wallets/temporary/local_devnet/spl_token_2022_validation/fixture.env" && test -f "$KB_DEVNET_TOKEN_2022_FIXTURE" && sed -n '/^export [A-Z0-9_]*=/p' "$KB_DEVNET_TOKEN_2022_FIXTURE" | sed 's/=.*$/=<défini>/' | tee "$KB_DEVNET_VALIDATION_DIR/50-spl-token-2022-fixture-keys.txt" && source "$KB_DEVNET_TOKEN_2022_FIXTURE"
|
export KS_DEVNET_TOKEN_2022_FIXTURE="$PWD/wallets/temporary/local_devnet/spl_token_2022_validation/fixture.env" && test -f "$KS_DEVNET_TOKEN_2022_FIXTURE" && sed -n '/^export [A-Z0-9_]*=/p' "$KS_DEVNET_TOKEN_2022_FIXTURE" | sed 's/=.*$/=<défini>/' | tee "$KS_DEVNET_VALIDATION_DIR/50-spl-token-2022-fixture-keys.txt" && source "$KS_DEVNET_TOKEN_2022_FIXTURE"
|
||||||
```
|
```
|
||||||
|
|
||||||
Afficher le mint et les trois comptes Token-2022 avec le Program ID explicite :
|
Afficher le mint et les trois comptes Token-2022 avec le Program ID explicite :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$TOKEN_2022_PROGRAM" display "$TOKEN_2022_MINT" && spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$TOKEN_2022_PROGRAM" display "$TOKEN_2022_SOURCE" && spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$TOKEN_2022_PROGRAM" display "$TOKEN_2022_DESTINATION" && spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$TOKEN_2022_PROGRAM" display "$TOKEN_2022_CLOSE_ACCOUNT"
|
spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID" display "$KS_PUBLIC_DEVNET_TOKEN_2022_MINT" && spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID" display "$KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE" && spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID" display "$KS_PUBLIC_DEVNET_TOKEN_2022_DESTINATION" && spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID" display "$KS_PUBLIC_DEVNET_TOKEN_2022_CLOSE_ACCOUNT"
|
||||||
```
|
```
|
||||||
|
|
||||||
Le compte `TOKEN_2022_CLOSE_ACCOUNT` doit rester vide jusqu'au scénario `CloseAccount`. Ne pas utiliser `account-info <adresse>` dans cette campagne : avec `spl-token-cli 5.5.0`, cette forme peut interpréter l'adresse comme un mint.
|
Le compte `KS_PUBLIC_DEVNET_TOKEN_2022_CLOSE_ACCOUNT` doit rester vide jusqu'au scénario `CloseAccount`. Ne pas utiliser `account-info <adresse>` dans cette campagne : avec `spl-token-cli 5.5.0`, cette forme peut interpréter l'adresse comme un mint.
|
||||||
|
|
||||||
### C12 — Preuves applicatives communes
|
### C12 — Preuves applicatives communes
|
||||||
|
|
||||||
@@ -331,7 +331,7 @@ Un scénario n’est validé que si le replay ne produit ni échec fonctionnel n
|
|||||||
6. Dans le terminal B, exécuter le contrôle de tables de `C05`.
|
6. Dans le terminal B, exécuter le contrôle de tables de `C05`.
|
||||||
7. Financer la pubkey par un faucet Web Devnet si le solde est insuffisant.
|
7. Financer la pubkey par un faucet Web Devnet si le solde est insuffisant.
|
||||||
8. Réexécuter `C04` dans le terminal B après financement.
|
8. Réexécuter `C04` dans le terminal B après financement.
|
||||||
9. Avant chaque scénario, définir `KB_DEVNET_SCENARIO` dans le terminal B, puis exécuter `C06`.
|
9. Avant chaque scénario, définir `KS_DEVNET_SCENARIO` dans le terminal B, puis exécuter `C06`.
|
||||||
|
|
||||||
## 6. Scénario S01 — Solana Core System Transfer
|
## 6. Scénario S01 — Solana Core System Transfer
|
||||||
|
|
||||||
@@ -344,7 +344,7 @@ Valider la chaîne complète : préparation, simulation, envoi, confirmation, st
|
|||||||
1. Définir puis exécuter `C06` :
|
1. Définir puis exécuter `C06` :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_SCENARIO="10-system-transfer"
|
export KS_DEVNET_SCENARIO="10-system-transfer"
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Dans la fenêtre **Exécution Devnet — Solana Core** :
|
2. Dans la fenêtre **Exécution Devnet — Solana Core** :
|
||||||
@@ -359,13 +359,13 @@ export KB_DEVNET_SCENARIO="10-system-transfer"
|
|||||||
4. Capturer séparément le solde du destinataire :
|
4. Capturer séparément le solde du destinataire :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_RECIPIENT="COLLER_LE_DESTINATAIRE"
|
export KS_DEVNET_RECIPIENT="COLLER_LE_DESTINATAIRE"
|
||||||
|
|
||||||
solana balance \
|
solana balance \
|
||||||
"$KB_DEVNET_RECIPIENT" \
|
"$KS_DEVNET_RECIPIENT" \
|
||||||
--url "$KB_DEVNET_RPC_URL" \
|
--url "$KS_DEVNET_RPC_URL" \
|
||||||
--commitment confirmed \
|
--commitment confirmed \
|
||||||
| tee "$KB_DEVNET_VALIDATION_DIR/${KB_DEVNET_SCENARIO}-recipient-after.txt"
|
| tee "$KS_DEVNET_VALIDATION_DIR/${KS_DEVNET_SCENARIO}-recipient-after.txt"
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Exécuter les contrôles applicatifs `C08` sur la signature.
|
5. Exécuter les contrôles applicatifs `C08` sur la signature.
|
||||||
@@ -398,7 +398,7 @@ Valider l’opération exécutable `spl.memo.add_memo`, l’événement observé
|
|||||||
1. Définir puis exécuter `C06` :
|
1. Définir puis exécuter `C06` :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_SCENARIO="20-spl-memo-v4"
|
export KS_DEVNET_SCENARIO="20-spl-memo-v4"
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Dans la fenêtre **Exécution Devnet — SPL** :
|
2. Dans la fenêtre **Exécution Devnet — SPL** :
|
||||||
@@ -407,7 +407,7 @@ export KB_DEVNET_SCENARIO="20-spl-memo-v4"
|
|||||||
- vérifier le Program ID `Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFaV3oAH` ;
|
- vérifier le Program ID `Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFaV3oAH` ;
|
||||||
- vérifier le wallet signer ;
|
- vérifier le wallet signer ;
|
||||||
- simuler puis confirmer l’envoi.
|
- simuler puis confirmer l’envoi.
|
||||||
3. Définir `KB_DEVNET_SIGNATURE` et exécuter `C07`.
|
3. Définir `KS_DEVNET_SIGNATURE` et exécuter `C07`.
|
||||||
4. Exécuter `C08` et vérifier précisément :
|
4. Exécuter `C08` et vérifier précisément :
|
||||||
- `processor_name = materializer.transaction.annotations` ;
|
- `processor_name = materializer.transaction.annotations` ;
|
||||||
- `surface_code = spl.memo.v4` ;
|
- `surface_code = spl.memo.v4` ;
|
||||||
@@ -441,22 +441,22 @@ Valider la dérivation et la création idempotente d’une ATA dont le mint appa
|
|||||||
2. Définir le scénario et capturer le solde :
|
2. Définir le scénario et capturer le solde :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_SCENARIO="30a-spl-ata-classic"
|
export KS_DEVNET_SCENARIO="30a-spl-ata-classic"
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Exécuter `C06`.
|
3. Exécuter `C06`.
|
||||||
4. Copier la valeur affichée par :
|
4. Copier la valeur affichée par :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
printf '%s\n' "$KB_DEVNET_CLASSIC_MINT"
|
printf '%s\n' "$KS_DEVNET_CLASSIC_MINT"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Procédure dans l’application
|
#### Procédure dans l’application
|
||||||
|
|
||||||
1. Ouvrir la fenêtre **SPL Associated Token Account**.
|
1. Ouvrir la fenêtre **SPL Associated Token Account**.
|
||||||
2. Utiliser :
|
2. Utiliser :
|
||||||
- owner : wallet opérateur `KB_DEVNET_WALLET_PUBKEY` ;
|
- owner : wallet opérateur `KS_PUBLIC_DEVNET_WALLET_ADDRESS` ;
|
||||||
- mint : `KB_DEVNET_CLASSIC_MINT` ;
|
- mint : `KS_DEVNET_CLASSIC_MINT` ;
|
||||||
- token program : SPL Token classique ;
|
- token program : SPL Token classique ;
|
||||||
- payer : wallet opérateur.
|
- payer : wallet opérateur.
|
||||||
3. Dériver l’ATA et conserver son adresse.
|
3. Dériver l’ATA et conserver son adresse.
|
||||||
@@ -464,7 +464,7 @@ printf '%s\n' "$KB_DEVNET_CLASSIC_MINT"
|
|||||||
5. Simuler `spl.associated_token_account.create_idempotent`.
|
5. Simuler `spl.associated_token_account.create_idempotent`.
|
||||||
6. Contrôler le rent ceiling, le payer, l’owner, le mint, le token program et l’adresse ATA dérivée.
|
6. Contrôler le rent ceiling, le payer, l’owner, le mint, le token program et l’adresse ATA dérivée.
|
||||||
7. Confirmer explicitement l’envoi.
|
7. Confirmer explicitement l’envoi.
|
||||||
8. Définir `KB_DEVNET_SIGNATURE`, puis exécuter `C07`.
|
8. Définir `KS_DEVNET_SIGNATURE`, puis exécuter `C07`.
|
||||||
9. Exécuter `C12`.
|
9. Exécuter `C12`.
|
||||||
10. Réexécuter la création idempotente et vérifier qu’elle ne produit ni fausse création ni duplication des projections.
|
10. Réexécuter la création idempotente et vérifier qu’elle ne produit ni fausse création ni duplication des projections.
|
||||||
|
|
||||||
@@ -480,28 +480,28 @@ Valider la dérivation et la création idempotente d’une ATA dont le mint appa
|
|||||||
2. Définir le scénario et capturer le solde :
|
2. Définir le scénario et capturer le solde :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_SCENARIO="30b-spl-ata-token-2022"
|
export KS_DEVNET_SCENARIO="30b-spl-ata-token-2022"
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Exécuter `C06`.
|
3. Exécuter `C06`.
|
||||||
4. Copier la valeur affichée par :
|
4. Copier la valeur affichée par :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
printf '%s\n' "$KB_DEVNET_TOKEN_2022_MINT"
|
printf '%s\n' "$KS_PUBLIC_DEVNET_TOKEN_2022_MINT"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Procédure dans l’application
|
#### Procédure dans l’application
|
||||||
|
|
||||||
1. Utiliser :
|
1. Utiliser :
|
||||||
- owner : le même wallet opérateur ;
|
- owner : le même wallet opérateur ;
|
||||||
- mint : `KB_DEVNET_TOKEN_2022_MINT` ;
|
- mint : `KS_PUBLIC_DEVNET_TOKEN_2022_MINT` ;
|
||||||
- token program : Token-2022 ;
|
- token program : Token-2022 ;
|
||||||
- payer : wallet opérateur.
|
- payer : wallet opérateur.
|
||||||
2. Dériver l’ATA et conserver son adresse.
|
2. Dériver l’ATA et conserver son adresse.
|
||||||
3. Vérifier que le Program ID sélectionné est `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`.
|
3. Vérifier que le Program ID sélectionné est `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`.
|
||||||
4. Vérifier que l’adresse dérivée diffère de l’ATA classique de S03A.
|
4. Vérifier que l’adresse dérivée diffère de l’ATA classique de S03A.
|
||||||
5. Simuler puis envoyer `spl.associated_token_account.create_idempotent`.
|
5. Simuler puis envoyer `spl.associated_token_account.create_idempotent`.
|
||||||
6. Définir `KB_DEVNET_SIGNATURE`, puis exécuter `C07`.
|
6. Définir `KS_DEVNET_SIGNATURE`, puis exécuter `C07`.
|
||||||
7. Exécuter `C12`.
|
7. Exécuter `C12`.
|
||||||
8. Rejouer la création idempotente.
|
8. Rejouer la création idempotente.
|
||||||
9. Vérifier séparément les faits parent ATA et les éventuels enfants CPI Token-2022, sans duplication.
|
9. Vérifier séparément les faits parent ATA et les éventuels enfants CPI Token-2022, sans duplication.
|
||||||
@@ -533,13 +533,13 @@ Elle ne permet pas encore d’enchaîner depuis l’interface `InitializeMint`,
|
|||||||
1. Réutiliser le mint classique de `C08` :
|
1. Réutiliser le mint classique de `C08` :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_SPL_TOKEN_PROGRAM_ID="TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" && export KB_DEVNET_CLASSIC_MINT_KEYPAIR="$PWD/wallets/temporary/local_devnet/mints/ata-classic-mint.json" && export KB_DEVNET_CLASSIC_MINT="$(solana-keygen pubkey "$KB_DEVNET_CLASSIC_MINT_KEYPAIR")"
|
export KS_PUBLIC_SPL_TOKEN_PROGRAM_ID="TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" && export KS_DEVNET_CLASSIC_MINT_KEYPAIR="$PWD/wallets/temporary/local_devnet/mints/ata-classic-mint.json" && export KS_DEVNET_CLASSIC_MINT="$(solana-keygen pubkey "$KS_DEVNET_CLASSIC_MINT_KEYPAIR")"
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Définir le scénario :
|
2. Définir le scénario :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_SCENARIO="40-spl-token"
|
export KS_DEVNET_SCENARIO="40-spl-token"
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Exécuter `C06`.
|
3. Exécuter `C06`.
|
||||||
@@ -547,7 +547,7 @@ export KB_DEVNET_SCENARIO="40-spl-token"
|
|||||||
5. Vérifier les comptes token avant l’opération :
|
5. Vérifier les comptes token avant l’opération :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" display "$KB_DEVNET_CLASSIC_SOURCE_ATA" && spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" display "$KB_DEVNET_CLASSIC_DESTINATION_ATA"
|
spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_PROGRAM_ID" display "$KS_DEVNET_CLASSIC_SOURCE_ATA" && spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_PROGRAM_ID" display "$KS_DEVNET_CLASSIC_DESTINATION_ATA"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Valeurs à saisir dans l’application
|
### Valeurs à saisir dans l’application
|
||||||
@@ -556,17 +556,17 @@ Dans **Décodeur spl_token — TransferChecked** :
|
|||||||
|
|
||||||
| Champ | Valeur |
|
| Champ | Valeur |
|
||||||
|--------------------|--------------------------------------------|
|
|--------------------|--------------------------------------------|
|
||||||
| Compte source | `$KB_DEVNET_CLASSIC_SOURCE_ATA` |
|
| Compte source | `$KS_DEVNET_CLASSIC_SOURCE_ATA` |
|
||||||
| Mint | `$KB_DEVNET_CLASSIC_MINT` |
|
| Mint | `$KS_DEVNET_CLASSIC_MINT` |
|
||||||
| Compte destination | `$KB_DEVNET_CLASSIC_DESTINATION_ATA` |
|
| Compte destination | `$KS_DEVNET_CLASSIC_DESTINATION_ATA` |
|
||||||
| Autorité simple | `$KB_DEVNET_WALLET_PUBKEY` |
|
| Autorité simple | `$KS_PUBLIC_DEVNET_WALLET_ADDRESS` |
|
||||||
| Montant brut exact | `1000000000` pour 1 token avec 9 décimales |
|
| Montant brut exact | `1000000000` pour 1 token avec 9 décimales |
|
||||||
| Decimals | `9` |
|
| Decimals | `9` |
|
||||||
|
|
||||||
Afficher les valeurs à copier :
|
Afficher les valeurs à copier :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
printf 'source=%s\nmint=%s\ndestination=%s\nauthority=%s\namount_raw=1000000000\ndecimals=9\n' "$KB_DEVNET_CLASSIC_SOURCE_ATA" "$KB_DEVNET_CLASSIC_MINT" "$KB_DEVNET_CLASSIC_DESTINATION_ATA" "$KB_DEVNET_WALLET_PUBKEY"
|
printf 'source=%s\nmint=%s\ndestination=%s\nauthority=%s\namount_raw=1000000000\ndecimals=9\n' "$KS_DEVNET_CLASSIC_SOURCE_ATA" "$KS_DEVNET_CLASSIC_MINT" "$KS_DEVNET_CLASSIC_DESTINATION_ATA" "$KS_PUBLIC_DEVNET_WALLET_ADDRESS"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exécution
|
### Exécution
|
||||||
@@ -584,14 +584,14 @@ printf 'source=%s\nmint=%s\ndestination=%s\nauthority=%s\namount_raw=1000000000\
|
|||||||
5. Copier la signature dans :
|
5. Copier la signature dans :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_SIGNATURE="SIGNATURE_SPL_TOKEN"
|
export KS_DEVNET_SIGNATURE="SIGNATURE_SPL_TOKEN"
|
||||||
```
|
```
|
||||||
|
|
||||||
6. Exécuter `C07`, puis `C12`.
|
6. Exécuter `C07`, puis `C12`.
|
||||||
7. Vérifier les comptes après transfert :
|
7. Vérifier les comptes après transfert :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" display "$KB_DEVNET_CLASSIC_SOURCE_ATA" && spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" display "$KB_DEVNET_CLASSIC_DESTINATION_ATA"
|
spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_PROGRAM_ID" display "$KS_DEVNET_CLASSIC_SOURCE_ATA" && spl-token --url "$KS_DEVNET_RPC_URL" --program-id "$KS_PUBLIC_SPL_TOKEN_PROGRAM_ID" display "$KS_DEVNET_CLASSIC_DESTINATION_ATA"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Critères de validation
|
### Critères de validation
|
||||||
@@ -614,7 +614,7 @@ Le journal métier SPL Token peut rester à `empty` après une simulation seule.
|
|||||||
1. Définir le scénario et exécuter `C06` :
|
1. Définir le scénario et exécuter `C06` :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_SCENARIO="50-spl-token-2022"
|
export KS_DEVNET_SCENARIO="50-spl-token-2022"
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Exécuter `C11` pour créer ou réutiliser la fixture.
|
2. Exécuter `C11` pour créer ou réutiliser la fixture.
|
||||||
@@ -647,7 +647,7 @@ Champs utilisés :
|
|||||||
- source/cible : compte token à créditer ;
|
- source/cible : compte token à créditer ;
|
||||||
- mint : mint Token-2022 ;
|
- mint : mint Token-2022 ;
|
||||||
- autorité : mint authority ;
|
- autorité : mint authority ;
|
||||||
- montant brut : `TOKEN_2022_MINT_AMOUNT_RAW` chargé depuis la fixture ;
|
- montant brut : `KS_PUBLIC_DEVNET_TOKEN_2022_MINT_AMOUNT_RAW` chargé depuis la fixture ;
|
||||||
- décimales : valeur de la fixture.
|
- décimales : valeur de la fixture.
|
||||||
|
|
||||||
Avec la fixture par défaut, le mint initial est `10000000000` unités brutes, soit 10 tokens avec 9 décimales. Cette quantité couvre ensuite le transfert, l'approbation et le burn prévus.
|
Avec la fixture par défaut, le mint initial est `10000000000` unités brutes, soit 10 tokens avec 9 décimales. Cette quantité couvre ensuite le transfert, l'approbation et le burn prévus.
|
||||||
@@ -732,13 +732,13 @@ Le compte doit être vide et satisfaire toutes les préconditions de fermeture.
|
|||||||
4. contrôler le plan, les owners, les autorités, le montant et les extensions ;
|
4. contrôler le plan, les owners, les autorités, le montant et les extensions ;
|
||||||
5. cocher la confirmation opérateur ;
|
5. cocher la confirmation opérateur ;
|
||||||
6. envoyer ;
|
6. envoyer ;
|
||||||
7. définir immédiatement `KB_DEVNET_SIGNATURE` avec la signature affichée pour cette sous-opération ;
|
7. définir immédiatement `KS_DEVNET_SIGNATURE` avec la signature affichée pour cette sous-opération ;
|
||||||
8. vérifier qu'elle diffère de la signature du scénario précédent, puis exécuter `C07` ;
|
8. vérifier qu'elle diffère de la signature du scénario précédent, puis exécuter `C07` ;
|
||||||
9. appliquer `C12` ;
|
9. appliquer `C12` ;
|
||||||
10. conserver un fichier de preuve distinct en modifiant temporairement le préfixe, par exemple :
|
10. conserver un fichier de preuve distinct en modifiant temporairement le préfixe, par exemple :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export KB_DEVNET_SCENARIO="50a-token-2022-mint-to-checked"
|
export KS_DEVNET_SCENARIO="50a-token-2022-mint-to-checked"
|
||||||
```
|
```
|
||||||
|
|
||||||
puis `50b`, `50c`, etc., avant chaque appel à `C07`.
|
puis `50b`, `50c`, etc., avant chaque appel à `C07`.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/architecture/CRATE_MAP.md -->
|
<!-- file: docs/architecture/CRATE_MAP.md -->
|
||||||
<!-- version: 4 -->
|
<!-- version: 5 -->
|
||||||
|
|
||||||
# Carte des crates
|
# Carte des crates
|
||||||
|
|
||||||
@@ -13,13 +13,13 @@
|
|||||||
| `ks-logging` | bibliothèque | initialisation du logging et du tracing | README/TODO/USAGE/CHANGELOG présents |
|
| `ks-logging` | bibliothèque | initialisation du logging et du tracing | README/TODO/USAGE/CHANGELOG présents |
|
||||||
| `ks-program-ids` | bibliothèque | registre des programmes et comptes Solana connus | README/TODO/USAGE/CHANGELOG présents |
|
| `ks-program-ids` | bibliothèque | registre des programmes et comptes Solana connus | README/TODO/USAGE/CHANGELOG présents |
|
||||||
| `ks-pipeline` | bibliothèque | backfill, extraction, replay, stateful, préflight et orchestration | README/TODO/USAGE/CHANGELOG présents |
|
| `ks-pipeline` | bibliothèque | backfill, extraction, replay, stateful, préflight et orchestration | README/TODO/USAGE/CHANGELOG présents |
|
||||||
| `ks-pipeline-demo-scenarios` | bibliothèque + binaire | scénarios Devnet réutilisables et CLI | renommage `0.5.1`, audit `0.5.4` |
|
| `ks-pipeline-demo-scenarios` | bibliothèque + binaire | scénarios Devnet réutilisables et CLI | nom `ks-*` actif ; audit `0.5.4` |
|
||||||
| `ks-onchain-transport` | bibliothèque | transports RPC HTTP/WebSocket et pools d’endpoints | README/TODO/USAGE/CHANGELOG présents |
|
| `ks-onchain-transport` | bibliothèque | transports RPC HTTP/WebSocket et pools d’endpoints | README/TODO/USAGE/CHANGELOG présents |
|
||||||
| `ks-store` | bibliothèque | contrats de stockage et adaptateur PostgreSQL | renommage `0.5.1`, normalisation `0.5.3` |
|
| `ks-store` | bibliothèque | contrats de stockage et adaptateur PostgreSQL | nom `ks-*` actif ; normalisation `0.5.3` |
|
||||||
| `ks-wallet` | bibliothèque | wallet temporaire et frontière de signataire | renommage `0.5.1`, refonte `0.5.2` |
|
| `ks-wallet` | bibliothèque | wallet temporaire et frontière de signataire | nom `ks-*` actif ; refonte `0.5.2` |
|
||||||
| `kb-app-demo-desktop` | bibliothèque + binaire | application de démonstration Tauri | documentée ; réconciliation en `0.5.4` |
|
| `kb-app-demo-desktop` | bibliothèque + binaire | application de démonstration Tauri | documentée ; réconciliation en `0.5.4` |
|
||||||
|
|
||||||
La table décrit les noms physiques du workspace `0.5.0`. La migration `0.5.1` renomme les dix crates généralistes en `ks-core`, `ks-config`, `ks-lib`, `ks-logging`, `ks-program-ids`, `ks-pipeline`, `ks-pipeline-demo-scenarios`, `ks-onchain-transport`, `ks-store` et `ks-wallet`. `kb-app-demo-desktop` conserve son nom parce qu’il appartient au domaine applicatif Bot. Voir [`../decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md`](../decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md).
|
La table décrit les noms physiques actifs depuis `0.5.1-pre.002`. La migration a renommé les dix crates généralistes en `ks-core`, `ks-config`, `ks-lib`, `ks-logging`, `ks-program-ids`, `ks-pipeline`, `ks-pipeline-demo-scenarios`, `ks-onchain-transport`, `ks-store` et `ks-wallet`. `kb-app-demo-desktop` conserve son nom parce qu’il appartient au domaine applicatif Bot. Voir [`../decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md`](../decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md).
|
||||||
|
|
||||||
## 2. Consolidations principales depuis bot2
|
## 2. Consolidations principales depuis bot2
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md -->
|
<!-- file: docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md -->
|
||||||
<!-- version: 4 -->
|
<!-- version: 5 -->
|
||||||
|
|
||||||
# Politique de namespace Khadhroony Solana
|
# Politique de namespace Khadhroony Solana
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
Cette décision est adoptée pendant la clôture de `0.5.0` et devient la cible normative des migrations de fondation `0.5.1` à `0.5.3`.
|
Cette décision est adoptée pendant la clôture de `0.5.0` et devient la cible normative des migrations de fondation `0.5.1` à `0.5.3`.
|
||||||
|
|
||||||
À partir de `0.5.1-pre.002`, les dix crates Solana généralistes sont physiquement nommées `ks-*` et leurs identifiants Rust `ks_*`. `0.5.1-pre.003` migre également les identités techniques `kb-lib.*` vers `ks-lib-*`. Les namespaces historiques `KB_*` et `kb_sol_*` restent temporairement présents jusqu'aux prereleases dédiées ; leur présence pendant cette migration bornée ne remet pas en cause la cible ci-dessous.
|
À partir de `0.5.1-pre.002`, les dix crates Solana généralistes sont physiquement nommées `ks-*` et leurs identifiants Rust `ks_*`. `0.5.1-pre.003` migre également les identités techniques `kb-lib.*` vers `ks-lib-*`. `0.5.1-pre.004` migre les variables possédées par Khadhroony Solana vers `KS_*` et réserve explicitement `KB_*` aux composants réellement possédés par Khadhroony Bot. Le namespace SQL `kb_sol_*` reste temporairement présent jusqu'à `0.5.3`.
|
||||||
|
|
||||||
Le renommage des bibliothèques internes ne renomme pas le workspace, le dépôt ni le répertoire racine : ils restent `khadhroony-bot3` pendant toute la série pré-`1.0`. Un éventuel renommage du workspace racine est explicitement hors périmètre de `0.5.x` et ne doit intervenir qu'en `1.0` ou ultérieurement sur décision dédiée.
|
Le renommage des bibliothèques internes ne renomme pas le workspace, le dépôt ni le répertoire racine : ils restent `khadhroony-bot3` pendant toute la série pré-`1.0`. Un éventuel renommage du workspace racine est explicitement hors périmètre de `0.5.x` et ne doit intervenir qu'en `1.0` ou ultérieurement sur décision dédiée.
|
||||||
|
|
||||||
@@ -44,17 +44,22 @@ La migration doit couvrir les manifests, chemins de workspace, imports, exports,
|
|||||||
|
|
||||||
## 4. Variables d'environnement
|
## 4. Variables d'environnement
|
||||||
|
|
||||||
Toutes les variables d'environnement appartenant aux contrats Khadhroony Solana/Bot doivent utiliser le namespace `KS_` après la migration `0.5.1`.
|
Le namespace d'une variable est déterminé par **la responsabilité qui possède le contrat**, et non par l'exécutable qui la lit.
|
||||||
|
|
||||||
Trois classes sont retenues :
|
- les crates et contrats généralistes Khadhroony Solana utilisent `KS_*` ;
|
||||||
|
- `kb-app-demo-desktop` et les futures crates réellement spécifiques au Bot utilisent `KB_*` pour leurs propres contrats ;
|
||||||
|
- une variable d'un scénario Solana réutilisable reste donc `KS_*` même lorsqu'elle est consommée par `kb-app-demo-desktop` ;
|
||||||
|
- les variables standard du système, de Cargo, de Rust ou d'un outil externe ne sont pas renommées artificiellement tant qu'elles ne deviennent pas un contrat de configuration du workspace.
|
||||||
|
|
||||||
- `KS_SECRET_*` : secret absolu ; la valeur peut être utilisée côté backend mais ne doit jamais être loggée, sérialisée vers une surface publique, renvoyée par Tauri ni affichée en diagnostic, même en mode debug ;
|
Chaque domaine possède les trois mêmes classes :
|
||||||
- `KS_PUBLIC_*` : valeur explicitement classée comme publiable ; le préfixe ne suffit pas à lui seul à autoriser une exposition, qui doit rester définie par un DTO ou une surface publique explicite ;
|
|
||||||
- `KS_*` hors sous-préfixes précédents : valeur interne ; elle n'est pas exposée en fonctionnement normal mais peut être incluse dans un diagnostic explicitement demandé si sa sémantique n'est pas sensible.
|
|
||||||
|
|
||||||
Une variable appartenant au workspace qui ne commence pas par `KS_` est non conforme après migration. Les variables standard du système ou de dépendances externes ne sont pas reclassées artificiellement comme variables de configuration Khadhroony.
|
- `KS_SECRET_*` / `KB_SECRET_*` : secret absolu ; la valeur peut être utilisée côté backend mais ne doit jamais être loggée, sérialisée vers une surface publique, renvoyée par Tauri ni affichée en diagnostic, même en mode debug ;
|
||||||
|
- `KS_PUBLIC_*` / `KB_PUBLIC_*` : valeur explicitement classée comme publiable ; le préfixe ne suffit pas à lui seul à autoriser une exposition, qui doit rester définie par un DTO ou une surface publique explicite ;
|
||||||
|
- `KS_*` / `KB_*` hors sous-préfixes précédents : valeur interne ; elle n'est pas exposée en fonctionnement normal mais peut être incluse dans un diagnostic explicitement demandé si sa sémantique n'est pas sensible.
|
||||||
|
|
||||||
La classification d'une valeur sensible doit survivre à la substitution. Une chaîne composée contenant une valeur issue de `KS_SECRET_*` reste sensible dans son ensemble et ne doit pas redevenir une simple valeur publiable après résolution.
|
Une variable appartenant à un contrat `ks-*` qui utilise `KB_*`, ou l'inverse pour un contrat réellement spécifique `kb-*`, est non conforme. `0.5.1-pre.004` ne laisse actuellement aucun contrat d'environnement propre au desktop : les variables qu'il consomme appartiennent toutes aux composants ou scénarios Solana et utilisent donc `KS_*`.
|
||||||
|
|
||||||
|
La classification d'une valeur sensible doit survivre à la substitution. Une chaîne composée contenant une valeur issue de `KS_SECRET_*` ou `KB_SECRET_*` reste sensible dans son ensemble et ne doit pas redevenir une simple valeur publiable après résolution. Cette propagation et le camouflage effectif sont implémentés après le split config/logging, pas dans la prerelease de renommage.
|
||||||
|
|
||||||
## 5. Configuration source, runtime et publique
|
## 5. Configuration source, runtime et publique
|
||||||
|
|
||||||
@@ -67,7 +72,7 @@ D'autres documents spécialisés ne sont créés que si l'audit démontre une re
|
|||||||
|
|
||||||
La conception doit distinguer :
|
La conception doit distinguer :
|
||||||
|
|
||||||
1. la représentation source, qui peut contenir des références `${KS_*}` ;
|
1. la représentation source, qui peut contenir des références `${KS_*}` ou `${KB_*}` selon le propriétaire du contrat ;
|
||||||
2. la représentation runtime résolue, qui peut porter des secrets ;
|
2. la représentation runtime résolue, qui peut porter des secrets ;
|
||||||
3. la représentation publique/diagnostique, construite explicitement et incapable d'exposer une valeur secrète résolue.
|
3. la représentation publique/diagnostique, construite explicitement et incapable d'exposer une valeur secrète résolue.
|
||||||
|
|
||||||
@@ -111,7 +116,7 @@ La migration `kb_sol_*` → `k_sol_*` doit être traitée avec les contrats temp
|
|||||||
|
|
||||||
## 8. Ordre des migrations
|
## 8. Ordre des migrations
|
||||||
|
|
||||||
- `0.5.1` : crates `ks-*`, identifiants Rust `ks_*`, variables `KS_*`, identités runtime/persistées Khadhroony Solana et restructuration sûre de la configuration/logging ;
|
- `0.5.1` : crates `ks-*`, identifiants Rust `ks_*`, variables `KS_*` pour Solana avec `KB_*` réservé aux contrats Bot, identités runtime/persistées Khadhroony Solana et restructuration sûre de la configuration/logging ;
|
||||||
- `0.5.2` : restructuration de `ks-wallet` sur la nouvelle fondation de configuration ;
|
- `0.5.2` : restructuration de `ks-wallet` sur la nouvelle fondation de configuration ;
|
||||||
- `0.5.3` : normalisation de `ks-store`, y compris migration du préfixe SQL vers `k_sol_*` et contrats temporels/provenance ;
|
- `0.5.3` : normalisation de `ks-store`, y compris migration du préfixe SQL vers `k_sol_*` et contrats temporels/provenance ;
|
||||||
- `0.5.4` : centralisation finale des scénarios dans `ks-pipeline-demo-scenarios` et audit de complétude des exécuteurs/validations.
|
- `0.5.4` : centralisation finale des scénarios dans `ks-pipeline-demo-scenarios` et audit de complétude des exécuteurs/validations.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/guides/CONFIGURATION.md -->
|
<!-- file: docs/guides/CONFIGURATION.md -->
|
||||||
<!-- version: 3 -->
|
<!-- version: 4 -->
|
||||||
|
|
||||||
# Guide de configuration
|
# Guide de configuration
|
||||||
|
|
||||||
@@ -11,32 +11,28 @@ Ce guide décrit le chargement et l’utilisation de la configuration bot3. La r
|
|||||||
|
|
||||||
- `config/example.config.json` : exemple utilisateur complet ;
|
- `config/example.config.json` : exemple utilisateur complet ;
|
||||||
- `config/schema.config.json` : contrat JSON formel ;
|
- `config/schema.config.json` : contrat JSON formel ;
|
||||||
- `.env` et variantes locales : valeurs d’environnement non versionnées ;
|
- `.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.
|
||||||
|
|
||||||
Le format actif est JSON. Le futur split de configuration prévu en `0.5.x` ne modifie pas le contrat actuel.
|
Le format actif est JSON. Le futur split de configuration prévu en `0.5.x` ne modifie pas le contrat actuel.
|
||||||
|
|
||||||
## Séquence de chargement
|
## Séquence de chargement
|
||||||
|
|
||||||
1. charger les fichiers d’environnement autorisés avec `load_workspace_environment` ;
|
L’API recommandée est `read_config_json_file_with_environment`. Elle :
|
||||||
2. lire le fichier JSON ;
|
|
||||||
3. résoudre les placeholders `${NAME}` ou `${NAME:-fallback}` ;
|
1. charge `.env`, ou le fichier explicitement sélectionné par `KS_ENV_FILE`, sans écraser les variables du processus ;
|
||||||
4. parser avec `load_config_from_str` ou `load_config_from_path` ;
|
2. lit le JSON ;
|
||||||
5. valider le schéma et les invariants typés ;
|
3. résout les placeholders namespacés `${KS_*}` / `${KB_*}` et les fallbacks éventuels ;
|
||||||
6. sélectionner le profil actif avec `active_profile`.
|
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
|
## Exemple opérateur
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let environment = match ks_config::load_workspace_environment(
|
let config = match ks_config::read_config_json_file_with_environment(
|
||||||
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_config::load_config_from_path(
|
|
||||||
std::path::Path::new("config/example.config.json"),
|
std::path::Path::new("config/example.config.json"),
|
||||||
|
std::path::Path::new("."),
|
||||||
) {
|
) {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
@@ -47,7 +43,6 @@ let profile = match ks_config::active_profile(&config) {
|
|||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("loaded environment files={}", environment.loaded_files.len());
|
|
||||||
println!("active profile={}", profile.name);
|
println!("active profile={}", profile.name);
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -56,7 +51,7 @@ println!("active profile={}", profile.name);
|
|||||||
- aucun secret ne doit être ajouté à l’exemple versionné ;
|
- aucun secret ne doit être ajouté à l’exemple versionné ;
|
||||||
- les placeholders non résolus doivent provoquer un diagnostic explicite ;
|
- les placeholders non résolus doivent provoquer un diagnostic explicite ;
|
||||||
- le schéma embarqué et `config/schema.config.json` doivent rester identiques ;
|
- le schéma embarqué et `config/schema.config.json` doivent rester identiques ;
|
||||||
- une sérialisation publique doit être précédée d’une validation ;
|
- 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.
|
- les noms de profils et rôles d’endpoints doivent rester cohérents avec leurs consommateurs.
|
||||||
|
|
||||||
## Quotas HTTP cumulés
|
## Quotas HTTP cumulés
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<!-- file: docs/plans/V0_5_1_KHADHROONY_SOLANA_NAMESPACE_AND_CONFIG_PLAN.md -->
|
<!-- file: docs/plans/V0_5_1_KHADHROONY_SOLANA_NAMESPACE_AND_CONFIG_PLAN.md -->
|
||||||
<!-- version: 3 -->
|
<!-- version: 4 -->
|
||||||
|
|
||||||
# Plan temporaire `0.5.1` — namespace Khadhroony Solana et configuration sûre
|
# Plan temporaire `0.5.1` — namespace Khadhroony Solana et configuration sûre
|
||||||
|
|
||||||
## 1. Statut et règle de cette prerelease
|
## 1. Statut et règle de cette prerelease
|
||||||
|
|
||||||
Ce document est le plan temporaire de `0.5.1`. `0.5.1-pre.001` a fermé l'inventaire et les contrats de migration. `0.5.1-pre.002` a renommé physiquement les dix crates Solana généralistes vers `ks-*` / `ks_*`. `0.5.1-pre.003` migre maintenant les identités runtime et persistables hiérarchiques de `ks-lib`, leurs routes de logging, matrices, tests et garde-fous, sans toucher aux variables d'environnement ni au namespace SQL. `kb-app-demo-desktop` et le workspace racine restent nommés comme avant.
|
Ce document est le plan temporaire de `0.5.1`. `0.5.1-pre.001` a fermé l'inventaire et les contrats de migration. `0.5.1-pre.002` a renommé physiquement les dix crates Solana généralistes vers `ks-*` / `ks_*`. `0.5.1-pre.003` a migré les identités runtime et persistables hiérarchiques de `ks-lib`. `0.5.1-pre.004` migre maintenant les contrats d’environnement vers les namespaces d’ownership `KS_*` / `KB_*`, sans toucher au namespace SQL ni encore scinder les fichiers de configuration. `kb-app-demo-desktop` et le workspace racine restent nommés comme avant.
|
||||||
|
|
||||||
La base `0.5.0-pre.004` puis `0.5.1-pre.001` ont été validées par `cargo fmt --all`, `cargo check --workspace`, `cargo clippy --all-targets`, `python3 scripts/audit_rust_workspace_rules.py` et `cargo test --workspace`. `pre.002` a ensuite été acceptée après validation opérateur du renommage physique. `pre.003` doit à nouveau rejouer ces contrôles, car les identités migrées alimentent les registres, matrices, diagnostics, routes de logging et contrats de replay.
|
La base `0.5.0-pre.004` puis `0.5.1-pre.001` ont été validées par `cargo fmt --all`, `cargo check --workspace`, `cargo clippy --all-targets`, `python3 scripts/audit_rust_workspace_rules.py` et `cargo test --workspace`. `pre.002` a ensuite été acceptée après validation opérateur du renommage physique. `pre.003` a été acceptée après validation opérateur. `pre.004` doit rejouer les contrôles de référence, car les noms d’environnement sont consommés par les tests optionnels, les scénarios, le store, la configuration et le desktop.
|
||||||
|
|
||||||
## 2. Invariant du workspace racine
|
## 2. Invariant du workspace racine
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ Pendant toute la série pré-`1.0`, sauf décision ultérieure explicite :
|
|||||||
workspace / repository / root directory = khadhroony-bot3
|
workspace / repository / root directory = khadhroony-bot3
|
||||||
```
|
```
|
||||||
|
|
||||||
Les bibliothèques internes Solana migrent vers `ks-*` / `ks_*` et leurs variables vers `KS_*`, mais elles restent membres du workspace `khadhroony-bot3`. Un éventuel renommage du workspace racine ne doit pas être entrepris avant `khadhroony-bot3` `1.0` ou une version ultérieure explicitement dédiée à cette opération.
|
Les bibliothèques internes Solana utilisent `ks-*` / `ks_*` et leurs variables possédées utilisent `KS_*`; les futurs contrats réellement spécifiques au Bot utiliseront `KB_*`. Elles restent toutes membres du workspace `khadhroony-bot3`. Un éventuel renommage du workspace racine ne doit pas être entrepris avant `khadhroony-bot3` `1.0` ou une version ultérieure explicitement dédiée à cette opération.
|
||||||
|
|
||||||
## 3. Frontière des domaines
|
## 3. Frontière des domaines
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ Les bibliothèques internes Solana migrent vers `ks-*` / `ks_*` et leurs variabl
|
|||||||
## 4. Inventaire des crates et ordre de migration
|
## 4. Inventaire des crates et ordre de migration
|
||||||
|
|
||||||
| Package actuel | Identifiant Rust actuel | Package cible | Identifiant Rust cible | Dépendances workspace directes actuelles | Ordre |
|
| Package actuel | Identifiant Rust actuel | Package cible | Identifiant Rust cible | Dépendances workspace directes actuelles | Ordre |
|
||||||
|------------------------------|------------------------------|------------------------------|------------------------------|----------------------------------------------------------------------------------------------------|------:|
|
|---|---|---|---|---|---:|
|
||||||
| `kb-core` | `kb_core` | `ks-core` | `ks_core` | — | 1 |
|
| `kb-core` | `kb_core` | `ks-core` | `ks_core` | — | 1 |
|
||||||
| `kb-program-ids` | `kb_program_ids` | `ks-program-ids` | `ks_program_ids` | — | 2 |
|
| `kb-program-ids` | `kb_program_ids` | `ks-program-ids` | `ks_program_ids` | — | 2 |
|
||||||
| `kb-config` | `kb_config` | `ks-config` | `ks_config` | kb-core | 3 |
|
| `kb-config` | `kb_config` | `ks-config` | `ks_config` | kb-core | 3 |
|
||||||
@@ -59,7 +59,7 @@ bin : kb-pipeline-demo-scenarios-cli -> ks-pipeline-demo-scenarios-cli
|
|||||||
Les valeurs suivantes sont des métriques d'orientation sur les fichiers actifs, hors archives et artefacts générés. Elles montrent qu'un renommage massif en une seule opération serait difficile à diagnostiquer.
|
Les valeurs suivantes sont des métriques d'orientation sur les fichiers actifs, hors archives et artefacts générés. Elles montrent qu'un renommage massif en une seule opération serait difficile à diagnostiquer.
|
||||||
|
|
||||||
| Crate | Références package / fichiers | Références identifiant Rust / fichiers |
|
| Crate | Références package / fichiers | Références identifiant Rust / fichiers |
|
||||||
|------------------------------|------------------------------:|---------------------------------------:|
|
|---|---:|---:|
|
||||||
| `kb-core` | 51 / 32 | 3165 / 407 |
|
| `kb-core` | 51 / 32 | 3165 / 407 |
|
||||||
| `kb-config` | 56 / 33 | 201 / 44 |
|
| `kb-config` | 56 / 33 | 201 / 44 |
|
||||||
| `kb-lib` | 3145 / 550 | 2785 / 97 |
|
| `kb-lib` | 3145 / 550 | 2785 / 97 |
|
||||||
@@ -146,7 +146,7 @@ Les targets de tracing de crates génériques doivent également migrer vers `ks
|
|||||||
### 6.1 Inventaire exhaustif des identités `kb-lib.*`
|
### 6.1 Inventaire exhaustif des identités `kb-lib.*`
|
||||||
|
|
||||||
| Identité actuelle | Identité cible |
|
| Identité actuelle | Identité cible |
|
||||||
|----------------------------------------------------------------|----------------------------------------------------------------|
|
|---|---|
|
||||||
| `kb-lib.decoder.adapter.saber_decimal_wrapper` | `ks-lib-decoder.adapter.saber_decimal_wrapper` |
|
| `kb-lib.decoder.adapter.saber_decimal_wrapper` | `ks-lib-decoder.adapter.saber_decimal_wrapper` |
|
||||||
| `kb-lib.decoder.adapter.spl_token_wrap` | `ks-lib-decoder.adapter.spl_token_wrap` |
|
| `kb-lib.decoder.adapter.spl_token_wrap` | `ks-lib-decoder.adapter.spl_token_wrap` |
|
||||||
| `kb-lib.decoder.admin.jupiter_lock` | `ks-lib-decoder.admin.jupiter_lock` |
|
| `kb-lib.decoder.admin.jupiter_lock` | `ks-lib-decoder.admin.jupiter_lock` |
|
||||||
@@ -408,9 +408,9 @@ 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 :
|
L'audit distingue trois ensembles afin de ne pas transformer des exemples historiques en contrats runtime :
|
||||||
|
|
||||||
- **82 noms** actuellement utilisés/référencés par le code, les tests, `.env.example` 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/example.config.json` ;
|
||||||
- **17 noms supplémentaires** présents uniquement dans le guide opérateur Devnet actif ;
|
- **17 noms supplémentaires** présents uniquement dans le guide opérateur Devnet actif ;
|
||||||
- soit **99 noms historiques actifs à migrer ou consolider**.
|
- soit **102 noms historiques actifs à migrer ou consolider**, dont plusieurs convergent volontairement vers une même cible canonique.
|
||||||
|
|
||||||
Le chiffre `84` mentionné dans un audit `0.5.0` était une estimation antérieure et ne doit plus être utilisé comme contrat.
|
Le chiffre `84` mentionné dans un audit `0.5.0` était une estimation antérieure et ne doit plus être utilisé comme contrat.
|
||||||
|
|
||||||
@@ -419,15 +419,19 @@ Le chiffre `84` mentionné dans un audit `0.5.0` était une estimation antérieu
|
|||||||
### 7.1 Politique cible
|
### 7.1 Politique cible
|
||||||
|
|
||||||
```text
|
```text
|
||||||
KS_SECRET_* -> secret absolu, jamais exposé, jamais loggé, jamais diagnostic en clair
|
Khadhroony Solana / ks-* : KS_SECRET_* / KS_PUBLIC_* / KS_*
|
||||||
KS_PUBLIC_* -> publiable uniquement via un DTO/surface explicitement autorisé
|
Khadhroony Bot / kb-* : KB_SECRET_* / KB_PUBLIC_* / KB_*
|
||||||
KS_* -> interne, non exposé normalement, diagnostic explicite seulement si non sensible
|
|
||||||
autre -> interdit pour une variable appartenant au workspace
|
|
||||||
```
|
```
|
||||||
|
|
||||||
La classification par préfixe est une barrière supplémentaire, pas la seule détection de sensibilité. Une URL `KS_*` contenant après substitution une clé API ou des credentials doit rester classée sensible dans son ensemble.
|
Le namespace suit le **propriétaire fonctionnel** du contrat. `kb-app-demo-desktop` peut donc lire une variable `KS_*` lorsqu'il adapte une capacité Solana ; cela ne transforme pas cette variable en contrat Bot. À l'issue de `pre.004`, aucun besoin d'environnement actuellement propre au desktop n'a été identifié : tous les noms runtime existants appartiennent à `ks-config`, `ks-store`, `ks-pipeline` ou `ks-pipeline-demo-scenarios`.
|
||||||
|
|
||||||
Aucune variable actuelle ne justifie d'être migrée par défaut en `KS_PUBLIC_*`. La migration part donc d'une politique fail-closed : quatre secrets certains deviennent `KS_SECRET_*`, les autres deviennent internes `KS_*`, puis une surface publique pourra être ajoutée plus tard seulement si son utilité est démontrée.
|
Dans chaque namespace :
|
||||||
|
|
||||||
|
- `*_SECRET_*` : jamais exposable ;
|
||||||
|
- `*_PUBLIC_*` : candidate explicite à une surface publique, mais seulement via un DTO/surface autorisé ;
|
||||||
|
- autre `KS_*` / `KB_*` : interne, diagnostic explicite seulement si non sensible.
|
||||||
|
|
||||||
|
La migration reste fail-closed. Les URLs PostgreSQL et la clé Helius sont des secrets certains. Les fixtures Token-2022 effectivement retournées au desktop sont classées `KS_PUBLIC_*`. Les autres contrôles de scénario restent internes. La propagation de sensibilité dans les valeurs composées et le camouflage effectif sont reportés après le split config/logging afin de ne pas mélanger renommage, restructuration et politique de sortie dans une seule prerelease.
|
||||||
|
|
||||||
Secrets certains :
|
Secrets certains :
|
||||||
|
|
||||||
@@ -438,12 +442,12 @@ KB_POSTGRES_MAINNET_URL -> KS_SECRET_POSTGRES_MAINNET_URL
|
|||||||
KB_POSTGRES_TEST_URL -> KS_SECRET_POSTGRES_TEST_URL
|
KB_POSTGRES_TEST_URL -> KS_SECRET_POSTGRES_TEST_URL
|
||||||
```
|
```
|
||||||
|
|
||||||
Les treize variables historiques `TOKEN_2022_*` sont des fixtures Devnet et convergent vers `KS_DEVNET_TOKEN_2022_*`. Lorsque cette convergence rencontre déjà une ancienne variable `KB_DEVNET_TOKEN_2022_*`, l'implémentation doit choisir **une seule variable cible** et détecter les conflits pendant la migration ; aucun double alias permanent n'est conservé.
|
Les anciennes fixtures `TOKEN_2022_*` et les alias opérateur déjà préfixés convergent vers **un seul vocabulaire**. Par exemple `TOKEN_2022_MINT` et `KB_DEVNET_TOKEN_2022_MINT` convergent vers `KS_PUBLIC_DEVNET_TOKEN_2022_MINT`; `TOKEN_2022_PROGRAM` et `KB_SPL_TOKEN_2022_PROGRAM_ID` convergent vers `KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID`; `KB_DEVNET_WALLET_ADDRESS` et `KB_DEVNET_WALLET_PUBKEY` convergent vers `KS_PUBLIC_DEVNET_WALLET_ADDRESS`. Aucun alias legacy permanent n'est conservé.
|
||||||
|
|
||||||
### 7.2 Mapping code/config/tests — 82 noms
|
### 7.2 Mapping code/config/tests — 85 noms
|
||||||
|
|
||||||
| Nom actuel | Nom cible | Classe |
|
| Nom actuel | Nom cible | Classe |
|
||||||
|--------------------------------------------------------------|--------------------------------------------------------------|------------|
|
|---|---|---|
|
||||||
| `HELIUS_API_KEY` | `KS_SECRET_HELIUS_API_KEY` | `secret` |
|
| `HELIUS_API_KEY` | `KS_SECRET_HELIUS_API_KEY` | `secret` |
|
||||||
| `KB_CONFIG_PATH` | `KS_CONFIG_PATH` | `internal` |
|
| `KB_CONFIG_PATH` | `KS_CONFIG_PATH` | `internal` |
|
||||||
| `KB_CONFIG_TEST_MISSING` | `KS_CONFIG_TEST_MISSING` | `internal` |
|
| `KB_CONFIG_TEST_MISSING` | `KS_CONFIG_TEST_MISSING` | `internal` |
|
||||||
@@ -507,30 +511,33 @@ Les treize variables historiques `TOKEN_2022_*` sont des fixtures Devnet et conv
|
|||||||
| `KB_DEVNET_TOKEN_2022_METADATA_OPERATOR_CONFIRMED` | `KS_DEVNET_TOKEN_2022_METADATA_OPERATOR_CONFIRMED` | `internal` |
|
| `KB_DEVNET_TOKEN_2022_METADATA_OPERATOR_CONFIRMED` | `KS_DEVNET_TOKEN_2022_METADATA_OPERATOR_CONFIRMED` | `internal` |
|
||||||
| `KB_DEVNET_TRANSFER_LAMPORTS` | `KS_DEVNET_TRANSFER_LAMPORTS` | `internal` |
|
| `KB_DEVNET_TRANSFER_LAMPORTS` | `KS_DEVNET_TRANSFER_LAMPORTS` | `internal` |
|
||||||
| `KB_DEVNET_WALLET` | `KS_DEVNET_WALLET` | `internal` |
|
| `KB_DEVNET_WALLET` | `KS_DEVNET_WALLET` | `internal` |
|
||||||
| `KB_DEVNET_WALLET_ADDRESS` | `KS_DEVNET_WALLET_ADDRESS` | `internal` |
|
| `KB_DEVNET_WALLET_ADDRESS` | `KS_PUBLIC_DEVNET_WALLET_ADDRESS` | `public` |
|
||||||
| `KB_DEVNET_WALLET_DIR` | `KS_DEVNET_WALLET_DIR` | `internal` |
|
| `KB_DEVNET_WALLET_DIR` | `KS_DEVNET_WALLET_DIR` | `internal` |
|
||||||
| `KB_ENV_FILE` | `KS_ENV_FILE` | `internal` |
|
| `KB_ENV_FILE` | `KS_ENV_FILE` | `internal` |
|
||||||
| `KB_POSTGRES_DEVNET_URL` | `KS_SECRET_POSTGRES_DEVNET_URL` | `secret` |
|
| `KB_POSTGRES_DEVNET_URL` | `KS_SECRET_POSTGRES_DEVNET_URL` | `secret` |
|
||||||
| `KB_POSTGRES_MAINNET_URL` | `KS_SECRET_POSTGRES_MAINNET_URL` | `secret` |
|
| `KB_POSTGRES_MAINNET_URL` | `KS_SECRET_POSTGRES_MAINNET_URL` | `secret` |
|
||||||
| `KB_POSTGRES_TEST_URL` | `KS_SECRET_POSTGRES_TEST_URL` | `secret` |
|
| `KB_POSTGRES_TEST_URL` | `KS_SECRET_POSTGRES_TEST_URL` | `secret` |
|
||||||
| `TOKEN_2022_APPROVE_AMOUNT_RAW` | `KS_DEVNET_TOKEN_2022_APPROVE_AMOUNT_RAW` | `internal` |
|
| `TOKEN_2022_APPROVE_AMOUNT_RAW` | `KS_PUBLIC_DEVNET_TOKEN_2022_APPROVE_AMOUNT_RAW` | `public` |
|
||||||
| `TOKEN_2022_AUTHORITY` | `KS_DEVNET_TOKEN_2022_AUTHORITY` | `internal` |
|
| `TOKEN_2022_AUTHORITY` | `KS_PUBLIC_DEVNET_TOKEN_2022_AUTHORITY` | `public` |
|
||||||
| `TOKEN_2022_BURN_AMOUNT_RAW` | `KS_DEVNET_TOKEN_2022_BURN_AMOUNT_RAW` | `internal` |
|
| `TOKEN_2022_BURN_AMOUNT_RAW` | `KS_PUBLIC_DEVNET_TOKEN_2022_BURN_AMOUNT_RAW` | `public` |
|
||||||
| `TOKEN_2022_CLOSE_ACCOUNT` | `KS_DEVNET_TOKEN_2022_CLOSE_ACCOUNT` | `internal` |
|
| `TOKEN_2022_CLOSE_ACCOUNT` | `KS_PUBLIC_DEVNET_TOKEN_2022_CLOSE_ACCOUNT` | `public` |
|
||||||
| `TOKEN_2022_DECIMALS` | `KS_DEVNET_TOKEN_2022_DECIMALS` | `internal` |
|
| `TOKEN_2022_DECIMALS` | `KS_PUBLIC_DEVNET_TOKEN_2022_DECIMALS` | `public` |
|
||||||
| `TOKEN_2022_DELEGATE` | `KS_DEVNET_TOKEN_2022_DELEGATE` | `internal` |
|
| `TOKEN_2022_DELEGATE` | `KS_PUBLIC_DEVNET_TOKEN_2022_DELEGATE` | `public` |
|
||||||
| `TOKEN_2022_DESTINATION` | `KS_DEVNET_TOKEN_2022_DESTINATION` | `internal` |
|
| `TOKEN_2022_DESTINATION` | `KS_PUBLIC_DEVNET_TOKEN_2022_DESTINATION` | `public` |
|
||||||
| `TOKEN_2022_FREEZE_AUTHORITY` | `KS_DEVNET_TOKEN_2022_FREEZE_AUTHORITY` | `internal` |
|
| `TOKEN_2022_FREEZE_AUTHORITY` | `KS_PUBLIC_DEVNET_TOKEN_2022_FREEZE_AUTHORITY` | `public` |
|
||||||
| `TOKEN_2022_MINT` | `KS_DEVNET_TOKEN_2022_MINT` | `internal` |
|
| `TOKEN_2022_MINT` | `KS_PUBLIC_DEVNET_TOKEN_2022_MINT` | `public` |
|
||||||
| `TOKEN_2022_MINT_AMOUNT_RAW` | `KS_DEVNET_TOKEN_2022_MINT_AMOUNT_RAW` | `internal` |
|
| `TOKEN_2022_MINT_AMOUNT_RAW` | `KS_PUBLIC_DEVNET_TOKEN_2022_MINT_AMOUNT_RAW` | `public` |
|
||||||
| `TOKEN_2022_PROGRAM` | `KS_DEVNET_TOKEN_2022_PROGRAM` | `internal` |
|
| `TOKEN_2022_PROGRAM` | `KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID` | `public` |
|
||||||
| `TOKEN_2022_SOURCE` | `KS_DEVNET_TOKEN_2022_SOURCE` | `internal` |
|
| `TOKEN_2022_SOURCE` | `KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE` | `public` |
|
||||||
| `TOKEN_2022_TRANSFER_AMOUNT_RAW` | `KS_DEVNET_TOKEN_2022_TRANSFER_AMOUNT_RAW` | `internal` |
|
| `TOKEN_2022_TRANSFER_AMOUNT_RAW` | `KS_PUBLIC_DEVNET_TOKEN_2022_TRANSFER_AMOUNT_RAW` | `public` |
|
||||||
|
| `ELGAMAL_REGISTRY_ADDRESS` | `KS_PUBLIC_DEVNET_ELGAMAL_REGISTRY_ADDRESS` | `public` |
|
||||||
|
| `ELGAMAL_PUBKEY_BASE64` | `KS_PUBLIC_DEVNET_ELGAMAL_PUBKEY_BASE64` | `public` |
|
||||||
|
| `PUBKEY_VALIDITY_PROOF_CONTEXT` | `KS_PUBLIC_DEVNET_PUBKEY_VALIDITY_PROOF_CONTEXT` | `public` |
|
||||||
|
|
||||||
### 7.3 Mapping guide opérateur Devnet — 17 noms
|
### 7.3 Mapping guide opérateur Devnet — 17 noms
|
||||||
|
|
||||||
| Nom actuel | Nom cible | Classe |
|
| Nom actuel | Nom cible | Classe |
|
||||||
|---------------------------------------|---------------------------------------|------------|
|
|---|---|---|
|
||||||
| `KB_CONFIRM_DEVNET_DATABASE_RESET` | `KS_CONFIRM_DEVNET_DATABASE_RESET` | `internal` |
|
| `KB_CONFIRM_DEVNET_DATABASE_RESET` | `KS_CONFIRM_DEVNET_DATABASE_RESET` | `internal` |
|
||||||
| `KB_DEVNET_CLASSIC_DESTINATION_ATA` | `KS_DEVNET_CLASSIC_DESTINATION_ATA` | `internal` |
|
| `KB_DEVNET_CLASSIC_DESTINATION_ATA` | `KS_DEVNET_CLASSIC_DESTINATION_ATA` | `internal` |
|
||||||
| `KB_DEVNET_CLASSIC_MINT` | `KS_DEVNET_CLASSIC_MINT` | `internal` |
|
| `KB_DEVNET_CLASSIC_MINT` | `KS_DEVNET_CLASSIC_MINT` | `internal` |
|
||||||
@@ -542,12 +549,12 @@ Les treize variables historiques `TOKEN_2022_*` sont des fixtures Devnet et conv
|
|||||||
| `KB_DEVNET_SCENARIO` | `KS_DEVNET_SCENARIO` | `internal` |
|
| `KB_DEVNET_SCENARIO` | `KS_DEVNET_SCENARIO` | `internal` |
|
||||||
| `KB_DEVNET_SIGNATURE` | `KS_DEVNET_SIGNATURE` | `internal` |
|
| `KB_DEVNET_SIGNATURE` | `KS_DEVNET_SIGNATURE` | `internal` |
|
||||||
| `KB_DEVNET_TOKEN_2022_FIXTURE` | `KS_DEVNET_TOKEN_2022_FIXTURE` | `internal` |
|
| `KB_DEVNET_TOKEN_2022_FIXTURE` | `KS_DEVNET_TOKEN_2022_FIXTURE` | `internal` |
|
||||||
| `KB_DEVNET_TOKEN_2022_MINT` | `KS_DEVNET_TOKEN_2022_MINT` | `internal` |
|
| `KB_DEVNET_TOKEN_2022_MINT` | `KS_PUBLIC_DEVNET_TOKEN_2022_MINT` | `public` |
|
||||||
| `KB_DEVNET_TOKEN_2022_MINT_KEYPAIR` | `KS_DEVNET_TOKEN_2022_MINT_KEYPAIR` | `internal` |
|
| `KB_DEVNET_TOKEN_2022_MINT_KEYPAIR` | `KS_DEVNET_TOKEN_2022_MINT_KEYPAIR` | `internal` |
|
||||||
| `KB_DEVNET_VALIDATION_DIR` | `KS_DEVNET_VALIDATION_DIR` | `internal` |
|
| `KB_DEVNET_VALIDATION_DIR` | `KS_DEVNET_VALIDATION_DIR` | `internal` |
|
||||||
| `KB_DEVNET_WALLET_PUBKEY` | `KS_DEVNET_WALLET_PUBKEY` | `internal` |
|
| `KB_DEVNET_WALLET_PUBKEY` | `KS_PUBLIC_DEVNET_WALLET_ADDRESS` | `public` |
|
||||||
| `KB_SPL_TOKEN_2022_PROGRAM_ID` | `KS_SPL_TOKEN_2022_PROGRAM_ID` | `internal` |
|
| `KB_SPL_TOKEN_2022_PROGRAM_ID` | `KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID` | `public` |
|
||||||
| `KB_SPL_TOKEN_PROGRAM_ID` | `KS_SPL_TOKEN_PROGRAM_ID` | `internal` |
|
| `KB_SPL_TOKEN_PROGRAM_ID` | `KS_PUBLIC_SPL_TOKEN_PROGRAM_ID` | `public` |
|
||||||
|
|
||||||
## 8. Split configuration / logging
|
## 8. Split configuration / logging
|
||||||
|
|
||||||
@@ -562,7 +569,7 @@ config/schema.logging.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`.
|
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`.
|
||||||
|
|
||||||
Le code duplique actuellement dans `kb-config` et `kb-logging` les concepts :
|
Le code duplique actuellement dans `ks-config` et `ks-logging` les concepts :
|
||||||
|
|
||||||
- `LoggingConfig` ;
|
- `LoggingConfig` ;
|
||||||
- `LogTargetConfig` ;
|
- `LogTargetConfig` ;
|
||||||
@@ -618,7 +625,7 @@ Avant chaque changement structurel correspondant, conserver ou ajouter des tests
|
|||||||
- le maintien de `khadhroony-bot3` comme nom racine ;
|
- le maintien de `khadhroony-bot3` comme nom racine ;
|
||||||
- la cohérence entre targets de tracing et routes de logging ;
|
- la cohérence entre targets de tracing et routes de logging ;
|
||||||
- la résolution des anciennes fixtures/env pendant la phase de migration uniquement, puis leur suppression ;
|
- la résolution des anciennes fixtures/env pendant la phase de migration uniquement, puis leur suppression ;
|
||||||
- l'interdiction des variables de configuration workspace hors `KS_*` ;
|
- 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 ;
|
- 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 ;
|
- 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 `schema.config.json` et `schema.logging.json` ;
|
||||||
@@ -653,13 +660,15 @@ Les tests ne doivent pas figer comme comportement légitime la fuite actuelle de
|
|||||||
- synchroniser routes de logging, matrices, diagnostics, tests et provenance/replay ;
|
- synchroniser routes de logging, matrices, diagnostics, tests et provenance/replay ;
|
||||||
- ne pas renommer encore les tables SQL `kb_sol_*`.
|
- ne pas renommer encore les tables SQL `kb_sol_*`.
|
||||||
|
|
||||||
### `0.5.1-pre.004` — environnement `KS_*` et classification
|
### `0.5.1-pre.004` — namespaces d’environnement et classification
|
||||||
|
|
||||||
- migrer code, tests, `.env.example`, configuration et guides vers `KS_*` ;
|
- migrer code, tests, `.env.example`, configuration et guides vers le namespace d’ownership `KS_*` ou `KB_*` ;
|
||||||
- consolider les aliases historiques Token-2022 ;
|
- consolider les aliases historiques Token-2022 ;
|
||||||
- introduire classification secret/public/internal et propagation de sensibilité ;
|
- matérialiser la classification secret/public/internal dans les noms et fermer les alias legacy ;
|
||||||
|
- reporter la propagation de sensibilité et le camouflage effectif après le split config/logging ;
|
||||||
- supprimer les anciens noms une fois la migration vérifiée ;
|
- supprimer les anciens noms une fois la migration vérifiée ;
|
||||||
- ajouter les canaris de non-divulgation.
|
- étendre l’audit workspace pour refuser la réintroduction de variables applicatives hors `KS_*` / `KB_*` dans le code, `.env.example`, la configuration exemple et le guide opérateur ;
|
||||||
|
- ne pas encore modifier les DTO publics ni implémenter le camouflage, qui appartiennent à `pre.006`.
|
||||||
|
|
||||||
### `0.5.1-pre.005` — split config/logging
|
### `0.5.1-pre.005` — split config/logging
|
||||||
|
|
||||||
@@ -715,7 +724,7 @@ Le desktop n'est lancé avec `cargo tauri dev` que lorsqu'une frontière runtime
|
|||||||
|
|
||||||
- les dix bibliothèques Solana utilisent `ks-*` / `ks_*` ;
|
- les dix bibliothèques Solana utilisent `ks-*` / `ks_*` ;
|
||||||
- le workspace racine s'appelle toujours `khadhroony-bot3` ;
|
- le workspace racine s'appelle toujours `khadhroony-bot3` ;
|
||||||
- les variables propres au workspace ont migré vers `KS_*` avec classification sûre ;
|
- les variables Solana ont migré vers `KS_*` avec classification nominale sûre et `KB_*` reste réservé aux futurs contrats Bot ;
|
||||||
- les identités techniques `kb-lib.*` ciblées ont disparu au profit de `ks-lib-*` ;
|
- les identités techniques `kb-lib.*` ciblées ont disparu au profit de `ks-lib-*` ;
|
||||||
- la configuration généraliste et logging sont séparées et validées indépendamment ;
|
- la configuration généraliste et logging sont séparées et validées indépendamment ;
|
||||||
- aucune configuration runtime résolue complète ne traverse Tauri ;
|
- aucune configuration runtime résolue complète ne traverse Tauri ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/rules/RULES_GENERAL.md -->
|
<!-- file: docs/rules/RULES_GENERAL.md -->
|
||||||
<!-- version: 5 -->
|
<!-- version: 6 -->
|
||||||
|
|
||||||
# Règles générales du projet
|
# Règles générales du projet
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
|
|
||||||
- Après le squelette initial, livrer uniquement des ZIP delta sauf demande explicite d’archive complète.
|
- Après le squelette initial, livrer uniquement des ZIP delta sauf demande explicite d’archive complète.
|
||||||
- Un delta touchant la racine ou plusieurs modules se nomme `khadhroony-bot3_vX.Y.Z-pre.abc-delta.zip`.
|
- Un delta touchant la racine ou plusieurs modules se nomme `khadhroony-bot3_vX.Y.Z-pre.abc-delta.zip`.
|
||||||
- Un delta limité à un package Rust se nomme `kb-modulename_vX.Y.Z-pre.abc-delta.zip`.
|
- Un delta limité à un package Rust utilise le nom Cargo courant du package : `<package>_vX.Y.Z-pre.abc-delta.zip` (par exemple `ks-config_vX.Y.Z-pre.abc-delta.zip` ou un futur package applicatif `kb-*`).
|
||||||
- Un correctif d’un delta déjà livré conserve le même numéro de prerelease et utilise `-delta-fix-001.zip`, puis `-fix-002.zip`, etc.
|
- Un correctif d’un delta déjà livré conserve le même numéro de prerelease et utilise `-delta-fix-001.zip`, puis `-fix-002.zip`, etc.
|
||||||
- La numérotation des correctifs recommence à `fix-001` pour chaque nouvelle prerelease.
|
- La numérotation des correctifs recommence à `fix-001` pour chaque nouvelle prerelease.
|
||||||
- Le numéro de prerelease suivant est réservé à une nouvelle tranche fonctionnelle.
|
- Le numéro de prerelease suivant est réservé à une nouvelle tranche fonctionnelle.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/rules/RULES_SPECIFIC_KHADHROONY.md -->
|
<!-- file: docs/rules/RULES_SPECIFIC_KHADHROONY.md -->
|
||||||
<!-- version: 14 -->
|
<!-- version: 15 -->
|
||||||
|
|
||||||
# Règles spécifiques à `khadhroony-bot3`
|
# Règles spécifiques à `khadhroony-bot3`
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ Toute divergence avec une règle générale doit être explicitement documentée
|
|||||||
- Les matérialisateurs doivent refuser les transactions non commitées pour les mutations d'état, tout en pouvant conserver séparément une intention non commitée lorsque le modèle métier le prévoit explicitement.
|
- Les matérialisateurs doivent refuser les transactions non commitées pour les mutations d'état, tout en pouvant conserver séparément une intention non commitée lorsque le modèle métier le prévoit explicitement.
|
||||||
- Toute absence volontaire de projection doit être documentée avec une justification technique précise. Un matérialisateur ne doit inventer ni état final, ni montant, ni autorité, ni frais, ni agrégation que l'observation ne prouve pas.
|
- Toute absence volontaire de projection doit être documentée avec une justification technique précise. Un matérialisateur ne doit inventer ni état final, ni montant, ni autorité, ni frais, ni agrégation que l'observation ne prouve pas.
|
||||||
- Chaque matérialisateur concret possède un composant structuré avec une façade limitée aux déclarations de sous-modules et réexports, un `constants.rs` et un `materializer.rs`. Les fichiers spécialisés `state.rs`, `account.rs` ou équivalents sont ajoutés seulement lorsque leur responsabilité est distincte.
|
- Chaque matérialisateur concret possède un composant structuré avec une façade limitée aux déclarations de sous-modules et réexports, un `constants.rs` et un `materializer.rs`. Les fichiers spécialisés `state.rs`, `account.rs` ou équivalents sont ajoutés seulement lorsque leur responsabilité est distincte.
|
||||||
- L’identité runtime suit `ks-lib-materializer.<domain>[.<subsystem>]`. Le `processorName` persisté suit `materializer.<domain>[.<subsystem>]` et doit être exactement l’identité runtime sans le préfixe `kb-lib.`. Le tracing target d’un composant actif est identique à son identité runtime.
|
- L’identité runtime suit `ks-lib-materializer.<domain>[.<subsystem>]`. Le `processorName` persisté suit `materializer.<domain>[.<subsystem>]` et doit être exactement l’identité runtime sans le préfixe `ks-lib-materializer`. Le tracing target d’un composant actif est identique à son identité runtime.
|
||||||
- Les constantes d’un composant utilisent le préfixe `MT_<COMPONENT>_`, résident dans son `constants.rs`, sont réexportées par chaque façade jusqu’à `ks-lib/src/lib.rs` et sont consommées par `crate::`, y compris dans les tests lorsqu’elles sont `pub` ou `pub(crate)`.
|
- Les constantes d’un composant utilisent le préfixe `MT_<COMPONENT>_`, résident dans son `constants.rs`, sont réexportées par chaque façade jusqu’à `ks-lib/src/lib.rs` et sont consommées par `crate::`, y compris dans les tests lorsqu’elles sont `pub` ou `pub(crate)`.
|
||||||
- Toute sortie persistée contient un `processorName` issu de la constante du composant et une `projectionVersion` explicite. Une correction de provenance persistée impose une nouvelle version de projection.
|
- Toute sortie persistée contient un `processorName` issu de la constante du composant et une `projectionVersion` explicite. Une correction de provenance persistée impose une nouvelle version de projection.
|
||||||
- Une coquille réservée implémente `MtMaterializer` et `MtApiEventMaterializer`, expose une constante `MT_*_ACCEPTED_FAMILIES` vide, refuse tous les événements, retourne une liste legacy vide et un résultat contextuel `Ignored`. Elle ne doit jamais créer un faux événement de transition.
|
- Une coquille réservée implémente `MtMaterializer` et `MtApiEventMaterializer`, expose une constante `MT_*_ACCEPTED_FAMILIES` vide, refuse tous les événements, retourne une liste legacy vide et un résultat contextuel `Ignored`. Elle ne doit jamais créer un faux événement de transition.
|
||||||
@@ -241,6 +241,9 @@ Aucun renommage massif de modules n'est autorisé sans étape de contrôle dédi
|
|||||||
- Les fichiers JSON de configuration ne doivent pas contenir de commentaires.
|
- 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 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é.
|
- Les valeurs sensibles doivent utiliser des variables d'environnement ou un stockage chiffré dédié.
|
||||||
|
- Les variables possédées par les composants généralistes `ks-*` utilisent obligatoirement `KS_SECRET_*`, `KS_PUBLIC_*` ou `KS_*` ; les variables réellement spécifiques à `kb-app-demo-desktop` ou à de futures crates `kb-*` utilisent `KB_SECRET_*`, `KB_PUBLIC_*` ou `KB_*`.
|
||||||
|
- Le namespace est déterminé par le propriétaire fonctionnel du contrat et non par son consommateur : une variable de scénario `ks-pipeline-demo-scenarios` reste `KS_*` même si le desktop la lit.
|
||||||
|
- Les sous-préfixes `SECRET` sont toujours non exposables ; les sous-préfixes `PUBLIC` ne sont exposables que par une surface explicitement autorisée ; les autres variables du domaine sont internes.
|
||||||
- Les structures de configuration exposées à Tauri doivent dériver `TS`.
|
- Les structures de configuration exposées à Tauri doivent dériver `TS`.
|
||||||
|
|
||||||
## Ordre de développement cible
|
## Ordre de développement cible
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
<!-- file: kb-app-demo-desktop/CHANGELOG.md -->
|
<!-- file: kb-app-demo-desktop/CHANGELOG.md -->
|
||||||
<!-- version: 43 -->
|
<!-- version: 44 -->
|
||||||
|
|
||||||
# CHANGELOG — kb-app-demo-desktop
|
# CHANGELOG — kb-app-demo-desktop
|
||||||
|
|
||||||
|
## `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 ;
|
||||||
|
- conserve le namespace applicatif `KB_*` disponible pour de futurs besoins réellement spécifiques au Bot, sans créer de variable Bot artificielle dans cette prerelease ;
|
||||||
|
- ne modifie aucun payload Tauri de configuration résolue : le camouflage et les DTO sûrs restent réservés à la prerelease dédiée après le split config/logging.
|
||||||
|
|
||||||
## `0.5.1-pre.002`
|
## `0.5.1-pre.002`
|
||||||
|
|
||||||
- adapte les dépendances Rust et tous les appels de crates Solana vers `ks_*` sans renommer l'application ;
|
- adapte les dépendances Rust et tous les appels de crates Solana vers `ks_*` sans renommer l'application ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-app-demo-desktop/src/app_state.rs
|
// file: kb-app-demo-desktop/src/app_state.rs
|
||||||
// version: 11
|
// version: 12
|
||||||
|
|
||||||
//! Shared Tauri application state and startup initialization.
|
//! Shared Tauri application state and startup initialization.
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ fn convert_logging_config(config: &ks_config::LoggingConfig) -> ks_logging::Logg
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_config_path() -> std::path::PathBuf {
|
fn resolve_config_path() -> std::path::PathBuf {
|
||||||
let configured = std::env::var("KB_CONFIG_PATH").ok();
|
let configured = std::env::var("KS_CONFIG_PATH").ok();
|
||||||
return resolve_config_path_from_value(configured.as_deref());
|
return resolve_config_path_from_value(configured.as_deref());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-app-demo-desktop/src/demo_spl_token_2022.rs
|
// file: kb-app-demo-desktop/src/demo_spl_token_2022.rs
|
||||||
// version: 13
|
// version: 14
|
||||||
|
|
||||||
//! Thin Tauri adapter for independent public Token-2022 Devnet validation scenarios.
|
//! Thin Tauri adapter for independent public Token-2022 Devnet validation scenarios.
|
||||||
|
|
||||||
@@ -247,46 +247,46 @@ pub(crate) fn demo_spl_token_2022_fixture(
|
|||||||
_ => std::result::Result::Err(format!("Token-2022 fixture is missing {name}")),
|
_ => std::result::Result::Err(format!("Token-2022 fixture is missing {name}")),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
let program_id = match required("TOKEN_2022_PROGRAM") {
|
let program_id = match required("KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
let mint = match required("TOKEN_2022_MINT") {
|
let mint = match required("KS_PUBLIC_DEVNET_TOKEN_2022_MINT") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
let source = match required("TOKEN_2022_SOURCE") {
|
let source = match required("KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
let destination = match required("TOKEN_2022_DESTINATION") {
|
let destination = match required("KS_PUBLIC_DEVNET_TOKEN_2022_DESTINATION") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
let close_account = match required("TOKEN_2022_CLOSE_ACCOUNT") {
|
let close_account = match required("KS_PUBLIC_DEVNET_TOKEN_2022_CLOSE_ACCOUNT") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
let delegate = match required("TOKEN_2022_DELEGATE") {
|
let delegate = match required("KS_PUBLIC_DEVNET_TOKEN_2022_DELEGATE") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
let authority = match required("TOKEN_2022_AUTHORITY") {
|
let authority = match required("KS_PUBLIC_DEVNET_TOKEN_2022_AUTHORITY") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
let freeze_authority = match required("TOKEN_2022_FREEZE_AUTHORITY") {
|
let freeze_authority = match required("KS_PUBLIC_DEVNET_TOKEN_2022_FREEZE_AUTHORITY") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
let decimals_text = match required("TOKEN_2022_DECIMALS") {
|
let decimals_text = match required("KS_PUBLIC_DEVNET_TOKEN_2022_DECIMALS") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
let decimals = match decimals_text.parse::<u8>() {
|
let decimals = match decimals_text.parse::<u8>() {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
return std::result::Result::Err(format!("invalid TOKEN_2022_DECIMALS value: {error}"));
|
return std::result::Result::Err(format!("invalid KS_PUBLIC_DEVNET_TOKEN_2022_DECIMALS value: {error}"));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return std::result::Result::Ok(crate::DemoSplToken2022FixturePayload {
|
return std::result::Result::Ok(crate::DemoSplToken2022FixturePayload {
|
||||||
@@ -300,19 +300,19 @@ pub(crate) fn demo_spl_token_2022_fixture(
|
|||||||
authority,
|
authority,
|
||||||
freeze_authority,
|
freeze_authority,
|
||||||
decimals,
|
decimals,
|
||||||
mint_amount_raw: match required("TOKEN_2022_MINT_AMOUNT_RAW") {
|
mint_amount_raw: match required("KS_PUBLIC_DEVNET_TOKEN_2022_MINT_AMOUNT_RAW") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
},
|
},
|
||||||
transfer_amount_raw: match required("TOKEN_2022_TRANSFER_AMOUNT_RAW") {
|
transfer_amount_raw: match required("KS_PUBLIC_DEVNET_TOKEN_2022_TRANSFER_AMOUNT_RAW") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
},
|
},
|
||||||
approve_amount_raw: match required("TOKEN_2022_APPROVE_AMOUNT_RAW") {
|
approve_amount_raw: match required("KS_PUBLIC_DEVNET_TOKEN_2022_APPROVE_AMOUNT_RAW") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
},
|
},
|
||||||
burn_amount_raw: match required("TOKEN_2022_BURN_AMOUNT_RAW") {
|
burn_amount_raw: match required("KS_PUBLIC_DEVNET_TOKEN_2022_BURN_AMOUNT_RAW") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
<!-- file: ks-config/CHANGELOG.md -->
|
<!-- file: ks-config/CHANGELOG.md -->
|
||||||
<!-- version: 13 -->
|
<!-- version: 14 -->
|
||||||
|
|
||||||
# CHANGELOG — ks-config
|
# CHANGELOG — ks-config
|
||||||
|
|
||||||
|
## `0.5.1-pre.004`
|
||||||
|
|
||||||
|
- migre le sélecteur d'environnement vers `KS_ENV_FILE` et les placeholders PostgreSQL/Helius vers `KS_SECRET_*` ;
|
||||||
|
- aligne `.env.example`, `config/example.config.json`, les tests et la documentation sur le namespace Khadhroony Solana ;
|
||||||
|
- ne met pas encore en œuvre le camouflage ou la propagation de sensibilité, réservés à la frontière runtime/public après le split config/logging.
|
||||||
|
|
||||||
## `0.5.1-pre.003`
|
## `0.5.1-pre.003`
|
||||||
|
|
||||||
- aligne `config/example.config.json` sur les identités hiérarchiques `ks-lib-*` afin que les routes de logging de référence suivent les producteurs renommés ;
|
- aligne `config/example.config.json` sur les identités hiérarchiques `ks-lib-*` afin que les routes de logging de référence suivent les producteurs renommés ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: ks-config/README.md -->
|
<!-- file: ks-config/README.md -->
|
||||||
<!-- version: 6 -->
|
<!-- version: 7 -->
|
||||||
|
|
||||||
# ks-config
|
# ks-config
|
||||||
|
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
- exposer `AppConfig` et les sections de configuration publiques ;
|
- exposer `AppConfig` et les sections de configuration publiques ;
|
||||||
- valider le JSON contre le schéma embarqué ;
|
- valider le JSON contre le schéma embarqué ;
|
||||||
- appliquer les invariants métier après désérialisation ;
|
- appliquer les invariants métier après désérialisation ;
|
||||||
- charger `.env` et `.env.local` depuis la racine du workspace ;
|
- charger `.env`, ou le fichier explicitement sélectionné par `KS_ENV_FILE`, depuis la racine du workspace ;
|
||||||
- résoudre les placeholders `${NAME}` et `${NAME:-fallback}` ;
|
- résoudre les placeholders namespacés `${KS_*}` / `${KB_*}` et leurs fallbacks ;
|
||||||
- sélectionner le profil actif ;
|
- sélectionner le profil actif ;
|
||||||
- exporter les types nécessaires au frontend avec `ts-rs`.
|
- exporter les types nécessaires au frontend avec `ts-rs`.
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ Les principales fonctions sont `read_config_json_file_with_environment`, `parse_
|
|||||||
|
|
||||||
## Statut
|
## 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, introduira le namespace d’environnement `KS_*` et séparera les représentations source, runtime et publiques afin qu’aucun secret résolu ne soit exposé.
|
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é.
|
||||||
|
|
||||||
## Documents
|
## Documents
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: ks-config/TODO.md -->
|
<!-- file: ks-config/TODO.md -->
|
||||||
<!-- version: 5 -->
|
<!-- version: 6 -->
|
||||||
|
|
||||||
# TODO — ks-config
|
# TODO — ks-config
|
||||||
|
|
||||||
@@ -8,12 +8,10 @@
|
|||||||
- [ ] `0.5.1` - séparer la configuration générale et le logging en documents et schémas JSON distincts.
|
- [ ] `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` - 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` - définir un propriétaire unique du contrat source logging et supprimer la conversion manuelle du desktop.
|
||||||
- [ ] `0.5.1` - migrer toutes les variables d’environnement propres au projet vers le namespace `KS_*`.
|
- [ ] `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` - appliquer les classes `KS_SECRET_*`, `KS_PUBLIC_*` et `KS_*` interne 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` - 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` - 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.
|
- [ ] `0.5.1` - supprimer l’exposition frontend de `AppConfig` et `ProfileConfig` résolus complets.
|
||||||
- [ ] Migration - fournir une table exhaustive des anciens noms d’environnement vers `KS_*` et une stratégie explicite pour le format `0.4.8`.
|
|
||||||
- [ ] Contrat - maintenir l’identité entre chaque schéma embarqué et son fichier sous `config/`.
|
- [ ] 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.
|
- [ ] 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.
|
- [ ] Documentation - mettre à jour guides, exemples et `.env.example` seulement avec l’implémentation correspondante.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: ks-config/USAGE.md -->
|
<!-- file: ks-config/USAGE.md -->
|
||||||
<!-- version: 5 -->
|
<!-- version: 6 -->
|
||||||
|
|
||||||
# Utilisation de ks-config
|
# Utilisation de ks-config
|
||||||
|
|
||||||
@@ -30,17 +30,17 @@ let report = match ks_config::load_workspace_environment(std::path::Path::new(".
|
|||||||
Err(error) => return Err(error),
|
Err(error) => return Err(error),
|
||||||
};
|
};
|
||||||
|
|
||||||
for path in report.loaded_files {
|
if let Some(path) = report.loaded_path {
|
||||||
println!("environment file: {}", path.display());
|
println!("environment file: {}", path.display());
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`EnvironmentLoadReport` indique les fichiers chargés. Les placeholders non résolus sans fallback restent visibles afin que la validation ou le consommateur puisse les signaler explicitement. Le format `0.4.8` accepte encore les anciens noms d’environnement ; la migration `0.5.1` imposera le namespace `KS_*`.
|
`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.
|
||||||
|
|
||||||
## Résolution explicite des placeholders
|
## Résolution explicite des placeholders
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let raw = r#"{"databaseUrl":"${KB_DATABASE_URL:-postgres://localhost/kb}"}"#;
|
let raw = r#"{"databaseUrl":"${KS_SECRET_POSTGRES_DEVNET_URL:-postgres://localhost/kb}"}"#;
|
||||||
let resolved = ks_config::resolve_environment_placeholders(raw);
|
let resolved = ks_config::resolve_environment_placeholders(raw);
|
||||||
|
|
||||||
assert!(resolved.contains("databaseUrl"));
|
assert!(resolved.contains("databaseUrl"));
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-config/src/environment.rs
|
// file: ks-config/src/environment.rs
|
||||||
// version: 4
|
// version: 5
|
||||||
|
|
||||||
//! Environment-file loading and configuration placeholder resolution.
|
//! Environment-file loading and configuration placeholder resolution.
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ pub struct EnvironmentLoadReport {
|
|||||||
pub fn load_workspace_environment(
|
pub fn load_workspace_environment(
|
||||||
workspace_root: &std::path::Path,
|
workspace_root: &std::path::Path,
|
||||||
) -> ks_core::Result<EnvironmentLoadReport> {
|
) -> ks_core::Result<EnvironmentLoadReport> {
|
||||||
let explicit_path = std::env::var("KB_ENV_FILE").ok();
|
let explicit_path = std::env::var("KS_ENV_FILE").ok();
|
||||||
let selected_path = match explicit_path {
|
let selected_path = match explicit_path {
|
||||||
std::option::Option::Some(path) if !path.trim().is_empty() => {
|
std::option::Option::Some(path) if !path.trim().is_empty() => {
|
||||||
let candidate = std::path::PathBuf::from(path);
|
let candidate = std::path::PathBuf::from(path);
|
||||||
@@ -82,14 +82,14 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn fallback_is_used_when_variable_is_absent() {
|
fn fallback_is_used_when_variable_is_absent() {
|
||||||
let resolved =
|
let resolved =
|
||||||
super::resolve_environment_placeholders("${KB_CONFIG_TEST_MISSING:-fallback}");
|
super::resolve_environment_placeholders("${KS_CONFIG_TEST_MISSING:-fallback}");
|
||||||
assert_eq!(resolved, "fallback");
|
assert_eq!(resolved, "fallback");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unresolved_required_placeholder_is_preserved() {
|
fn unresolved_required_placeholder_is_preserved() {
|
||||||
let resolved =
|
let resolved =
|
||||||
super::resolve_environment_placeholders("prefix-${KB_CONFIG_TEST_MISSING}-suffix");
|
super::resolve_environment_placeholders("prefix-${KS_CONFIG_TEST_MISSING}-suffix");
|
||||||
assert_eq!(resolved, "prefix-${KB_CONFIG_TEST_MISSING}-suffix");
|
assert_eq!(resolved, "prefix-${KS_CONFIG_TEST_MISSING}-suffix");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-config/src/settings.rs
|
// file: ks-config/src/settings.rs
|
||||||
// version: 18
|
// version: 19
|
||||||
|
|
||||||
//! Typed configuration models shared by applications and workers.
|
//! Typed configuration models shared by applications and workers.
|
||||||
|
|
||||||
@@ -1453,15 +1453,15 @@ mod tests {
|
|||||||
let value = parse_example_value();
|
let value = parse_example_value();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
value["profiles"][0]["database"]["postgres"]["url"],
|
value["profiles"][0]["database"]["postgres"]["url"],
|
||||||
serde_json::Value::String("${KB_POSTGRES_DEVNET_URL}".to_string())
|
serde_json::Value::String("${KS_SECRET_POSTGRES_DEVNET_URL}".to_string())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
value["profiles"][1]["database"]["postgres"]["url"],
|
value["profiles"][1]["database"]["postgres"]["url"],
|
||||||
serde_json::Value::String("${KB_POSTGRES_MAINNET_URL}".to_string())
|
serde_json::Value::String("${KS_SECRET_POSTGRES_MAINNET_URL}".to_string())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
value["profiles"][2]["database"]["postgres"]["url"],
|
value["profiles"][2]["database"]["postgres"]["url"],
|
||||||
serde_json::Value::String("${KB_POSTGRES_MAINNET_URL}".to_string())
|
serde_json::Value::String("${KS_SECRET_POSTGRES_MAINNET_URL}".to_string())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1487,7 +1487,7 @@ mod tests {
|
|||||||
fn schema_rejects_unknown_endpoint_secret_field() {
|
fn schema_rejects_unknown_endpoint_secret_field() {
|
||||||
let mut value = parse_example_value();
|
let mut value = parse_example_value();
|
||||||
value["profiles"][0]["solana"]["http_endpoints"][0]["secret_env_field"] =
|
value["profiles"][0]["solana"]["http_endpoints"][0]["secret_env_field"] =
|
||||||
serde_json::Value::String("HELIUS_API_KEY".to_string());
|
serde_json::Value::String("KS_SECRET_HELIUS_API_KEY".to_string());
|
||||||
let raw_json = value_to_json(&value);
|
let raw_json = value_to_json(&value);
|
||||||
let result = super::validate_config_json_schema(&raw_json);
|
let result = super::validate_config_json_schema(&raw_json);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
<!-- file: ks-pipeline-demo-scenarios/CHANGELOG.md -->
|
<!-- file: ks-pipeline-demo-scenarios/CHANGELOG.md -->
|
||||||
<!-- version: 74 -->
|
<!-- version: 75 -->
|
||||||
|
|
||||||
# CHANGELOG — ks-pipeline-demo-scenarios
|
# CHANGELOG — ks-pipeline-demo-scenarios
|
||||||
|
|
||||||
|
## `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_*` ;
|
||||||
|
- consolide les fixtures Token-2022 exposées au desktop sous `KS_PUBLIC_*`, sans conserver les anciens aliases `TOKEN_2022_*` / `KB_*` ;
|
||||||
|
- aligne le CLI, les campagnes Devnet, le rendu `fixture.env` et le guide d'utilisation sans rejouer ni requalifier les scénarios réseau.
|
||||||
|
|
||||||
## `0.5.1-pre.002`
|
## `0.5.1-pre.002`
|
||||||
|
|
||||||
- renomme `kb-pipeline-demo-scenarios` en `ks-pipeline-demo-scenarios`, sa bibliothèque en `ks_pipeline_demo_scenarios` et son CLI en `ks-pipeline-demo-scenarios-cli` ;
|
- renomme `kb-pipeline-demo-scenarios` en `ks-pipeline-demo-scenarios`, sa bibliothèque en `ks_pipeline_demo_scenarios` et son CLI en `ks-pipeline-demo-scenarios-cli` ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: ks-pipeline-demo-scenarios/USAGE.md -->
|
<!-- file: ks-pipeline-demo-scenarios/USAGE.md -->
|
||||||
<!-- version: 27 -->
|
<!-- version: 28 -->
|
||||||
|
|
||||||
# Utilisation de ks-pipeline-demo-scenarios
|
# Utilisation de ks-pipeline-demo-scenarios
|
||||||
|
|
||||||
@@ -107,13 +107,13 @@ La campagne `0.4.8-pre.012` prépare un mint Token-2022 frais, initialise son `M
|
|||||||
Le test opt-in est le chemin opérateur recommandé :
|
Le test opt-in est le chemin opérateur recommandé :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
KB_DEVNET_TOKEN_2022_METADATA_CAMPAIGN_TEST=1 \
|
KS_DEVNET_TOKEN_2022_METADATA_CAMPAIGN_TEST=1 \
|
||||||
KB_DEVNET_TOKEN_2022_METADATA_OPERATOR_CONFIRMED=1 \
|
KS_DEVNET_TOKEN_2022_METADATA_OPERATOR_CONFIRMED=1 \
|
||||||
KB_POSTGRES_TEST_URL='postgresql://…' \
|
KS_SECRET_POSTGRES_TEST_URL='postgresql://…' \
|
||||||
cargo test -p ks-pipeline-demo-scenarios optional_devnet_token_2022_metadata_campaign_from_env -- --nocapture
|
cargo test -p ks-pipeline-demo-scenarios optional_devnet_token_2022_metadata_campaign_from_env -- --nocapture
|
||||||
```
|
```
|
||||||
|
|
||||||
`KB_DEVNET_PROFILE` peut sélectionner explicitement le profil Devnet et `KB_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/example.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.
|
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.
|
||||||
|
|
||||||
@@ -299,22 +299,22 @@ La matrice ne transforme jamais une implémentation disponible en validation ré
|
|||||||
Le runner Devnet commun accepte toute variante non dépréciée de `ExMetaplexTokenMetadataOperation`. Le test opt-in peut être lancé avec :
|
Le runner Devnet commun accepte toute variante non dépréciée de `ExMetaplexTokenMetadataOperation`. Le test opt-in peut être lancé avec :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
KB_DEVNET_METAPLEX_EXECUTION_TEST=1 \
|
KS_DEVNET_METAPLEX_EXECUTION_TEST=1 \
|
||||||
KB_DEVNET_METAPLEX_OPERATION_JSON='{"operation":"..."}' \
|
KS_DEVNET_METAPLEX_OPERATION_JSON='{"operation":"..."}' \
|
||||||
cargo test -p ks-pipeline-demo-scenarios optional_devnet_current_operation_from_env -- --nocapture
|
cargo test -p ks-pipeline-demo-scenarios optional_devnet_current_operation_from_env -- --nocapture
|
||||||
```
|
```
|
||||||
|
|
||||||
Variables optionnelles :
|
Variables optionnelles :
|
||||||
|
|
||||||
- `KB_DEVNET_WALLET_DIR` pour sélectionner le répertoire du wallet persistant ;
|
- `KS_DEVNET_WALLET_DIR` pour sélectionner le répertoire du wallet persistant ;
|
||||||
- `KB_POSTGRES_TEST_URL` est obligatoire pour le test opt-in afin de permettre l’hydratation canonique, l’extraction Core, le replay et la vérification d’idempotence après une soumission ;
|
- `KS_SECRET_POSTGRES_TEST_URL` est obligatoire pour le test opt-in afin de permettre l’hydratation canonique, l’extraction Core, le replay et la vérification d’idempotence après une soumission ;
|
||||||
- `KB_DEVNET_METAPLEX_PREFLIGHT_READS_JSON` pour fournir les lectures stateful avant simulation ;
|
- `KS_DEVNET_METAPLEX_PREFLIGHT_READS_JSON` pour fournir les lectures stateful avant simulation ;
|
||||||
- `KB_DEVNET_METAPLEX_POSTCONDITION_READS_JSON` pour fournir les lectures après confirmation ;
|
- `KS_DEVNET_METAPLEX_POSTCONDITION_READS_JSON` pour fournir les lectures après confirmation ;
|
||||||
- `KB_DEVNET_METAPLEX_MATERIALIZE_AFTER_CONFIRMATION=1` pour rendre obligatoire la preuve de matérialisation et produire les snapshots stateful demandés ;
|
- `KS_DEVNET_METAPLEX_MATERIALIZE_AFTER_CONFIRMATION=1` pour rendre obligatoire la preuve de matérialisation et produire les snapshots stateful demandés ;
|
||||||
- `KB_DEVNET_METAPLEX_SUBMIT=1` pour autoriser la soumission ;
|
- `KS_DEVNET_METAPLEX_SUBMIT=1` pour autoriser la soumission ;
|
||||||
- `KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1` pour confirmer explicitement la soumission.
|
- `KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1` pour confirmer explicitement la soumission.
|
||||||
|
|
||||||
La soumission reste impossible si `KB_DEVNET_METAPLEX_SUBMIT` et `KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED` ne sont pas activées ensemble. Après confirmation, le runner hydrate la transaction canonique, exécute l’extraction Core, rejoue le décodeur Metaplex avec ses matérialiseurs puis effectue une seconde passe qui doit être idempotente. Les opérations dépréciées sont rejetées avant tout appel RPC.
|
La soumission reste impossible si `KS_DEVNET_METAPLEX_SUBMIT` et `KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED` ne sont pas activées ensemble. Après confirmation, le runner hydrate la transaction canonique, exécute l’extraction Core, rejoue le décodeur Metaplex avec ses matérialiseurs puis effectue une seconde passe qui doit être idempotente. Les opérations dépréciées sont rejetées avant tout appel RPC.
|
||||||
|
|
||||||
## Préparer une campagne Metaplex courante
|
## Préparer une campagne Metaplex courante
|
||||||
|
|
||||||
@@ -354,7 +354,7 @@ fn creator_verify_request(
|
|||||||
|
|
||||||
`devnet_metaplex_creator_unverify_request` fournit le parcours inverse. Les deux requêtes restent en simulation-only par défaut.
|
`devnet_metaplex_creator_unverify_request` fournit le parcours inverse. Les deux requêtes restent en simulation-only par défaut.
|
||||||
|
|
||||||
Le test générique accepte toujours `KB_DEVNET_METAPLEX_OPERATION_JSON`, mais rejette explicitement le placeholder documentaire `...`. Les opérations plus complexes recevront des préparateurs de fixtures dédiés au lieu d’exiger de longs JSON écrits à la main.
|
Le test générique accepte toujours `KS_DEVNET_METAPLEX_OPERATION_JSON`, mais rejette explicitement le placeholder documentaire `...`. Les opérations plus complexes recevront des préparateurs de fixtures dédiés au lieu d’exiger de longs JSON écrits à la main.
|
||||||
|
|
||||||
## Préparer `Create` puis `Mint` avec un ATA canonique
|
## Préparer `Create` puis `Mint` avec un ATA canonique
|
||||||
|
|
||||||
@@ -374,13 +374,13 @@ Le token record pNFT est uniquement dérivé pendant la préparation. Sa créati
|
|||||||
|
|
||||||
La campagne est volontairement exécutée **une famille à la fois**. Elle prépare une fixture fraîche, soumet `Create`, vérifie que la supply et l’ATA restent à zéro, puis soumet `Mint` et exige la transition exacte vers `mint_amount_raw`. Pour NFT, collection et pNFT, la validation SPL exige après `Create` que les mint/freeze authorities aient été transférées au PDA Master Edition ; pour SFT et fungible, elles restent sur l’opérateur. Après `Mint`, NFT/SFT/fungible/collection exigent un ATA `Initialized` (`state=1`), alors que pNFT exige un ATA `Frozen` (`state=2`) et un Token Record Metaplex présent. Toutes les lectures Metaplex postcondition sont automatiquement bornées au slot de confirmation.
|
La campagne est volontairement exécutée **une famille à la fois**. Elle prépare une fixture fraîche, soumet `Create`, vérifie que la supply et l’ATA restent à zéro, puis soumet `Mint` et exige la transition exacte vers `mint_amount_raw`. Pour NFT, collection et pNFT, la validation SPL exige après `Create` que les mint/freeze authorities aient été transférées au PDA Master Edition ; pour SFT et fungible, elles restent sur l’opérateur. Après `Mint`, NFT/SFT/fungible/collection exigent un ATA `Initialized` (`state=1`), alors que pNFT exige un ATA `Frozen` (`state=2`) et un Token Record Metaplex présent. Toutes les lectures Metaplex postcondition sont automatiquement bornées au slot de confirmation.
|
||||||
|
|
||||||
Le test opt-in utilise `nft` par défaut. Les valeurs acceptées par `KB_DEVNET_METAPLEX_CREATE_MINT_FAMILY` sont `nft`, `sft`, `fungible`, `collection`, `programmable_nft` et l’alias `pnft`.
|
Le test opt-in utilise `nft` par défaut. Les valeurs acceptées par `KS_DEVNET_METAPLEX_CREATE_MINT_FAMILY` sont `nft`, `sft`, `fungible`, `collection`, `programmable_nft` et l’alias `pnft`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
KB_DEVNET_METAPLEX_CREATE_MINT_CAMPAIGN_TEST=1 \
|
KS_DEVNET_METAPLEX_CREATE_MINT_CAMPAIGN_TEST=1 \
|
||||||
KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
|
KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
|
||||||
KB_DEVNET_METAPLEX_CREATE_MINT_FAMILY=nft \
|
KS_DEVNET_METAPLEX_CREATE_MINT_FAMILY=nft \
|
||||||
KB_POSTGRES_TEST_URL='postgresql://…' \
|
KS_SECRET_POSTGRES_TEST_URL='postgresql://…' \
|
||||||
cargo test -p ks-pipeline-demo-scenarios \
|
cargo test -p ks-pipeline-demo-scenarios \
|
||||||
optional_devnet_metaplex_create_mint_campaign_from_env \
|
optional_devnet_metaplex_create_mint_campaign_from_env \
|
||||||
-- --nocapture
|
-- --nocapture
|
||||||
@@ -403,9 +403,9 @@ La preuve stateful exige simultanément :
|
|||||||
Le parcours ne soumet pas `SetCollectionSize` : cette opération est obsolète et ne doit pas fabriquer artificiellement la postcondition de taille.
|
Le parcours ne soumet pas `SetCollectionSize` : cette opération est obsolète et ne doit pas fabriquer artificiellement la postcondition de taille.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
KB_DEVNET_METAPLEX_COLLECTION_VERIFY_CAMPAIGN_TEST=1 \
|
KS_DEVNET_METAPLEX_COLLECTION_VERIFY_CAMPAIGN_TEST=1 \
|
||||||
KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
|
KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
|
||||||
KB_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
|
KS_SECRET_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
|
||||||
cargo test -p ks-pipeline-demo-scenarios \
|
cargo test -p ks-pipeline-demo-scenarios \
|
||||||
optional_devnet_metaplex_collection_verify_campaign_from_env \
|
optional_devnet_metaplex_collection_verify_campaign_from_env \
|
||||||
-- --nocapture
|
-- --nocapture
|
||||||
@@ -426,9 +426,9 @@ Une exécution réussie imprime `METAPLEX_COLLECTION_VERIFY_FIXTURE`, deux ligne
|
|||||||
Le runner exige que le Token Record source passe `Unlocked/Staking -> Locked/Staking -> Unlocked/Staking -> delegate cleared -> Unlocked/Transfer`. Après le transfert, l’ATA source doit contenir `0` et rester `Initialized`, tandis que l’ATA destination doit contenir `1` et rester `Frozen`; le Token Record destination doit être `Unlocked` sans delegate. Ce contrat suit le handler courant, qui thaw la source avant transfert puis freeze uniquement la destination. Les wallets temporaires ne remplacent jamais le wallet persistant du profil comme fee payer ; seul le delegate explicitement déclaré est ajouté aux signataires des étapes qui l’exigent.
|
Le runner exige que le Token Record source passe `Unlocked/Staking -> Locked/Staking -> Unlocked/Staking -> delegate cleared -> Unlocked/Transfer`. Après le transfert, l’ATA source doit contenir `0` et rester `Initialized`, tandis que l’ATA destination doit contenir `1` et rester `Frozen`; le Token Record destination doit être `Unlocked` sans delegate. Ce contrat suit le handler courant, qui thaw la source avant transfert puis freeze uniquement la destination. Les wallets temporaires ne remplacent jamais le wallet persistant du profil comme fee payer ; seul le delegate explicitement déclaré est ajouté aux signataires des étapes qui l’exigent.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
KB_DEVNET_METAPLEX_PNFT_LIFECYCLE_CAMPAIGN_TEST=1 \
|
KS_DEVNET_METAPLEX_PNFT_LIFECYCLE_CAMPAIGN_TEST=1 \
|
||||||
KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
|
KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
|
||||||
KB_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
|
KS_SECRET_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
|
||||||
cargo test -p ks-pipeline-demo-scenarios \
|
cargo test -p ks-pipeline-demo-scenarios \
|
||||||
optional_devnet_metaplex_pnft_lifecycle_campaign_from_env \
|
optional_devnet_metaplex_pnft_lifecycle_campaign_from_env \
|
||||||
-- --nocapture
|
-- --nocapture
|
||||||
@@ -441,9 +441,9 @@ Une exécution qualifiante doit terminer `ok` et produire `METAPLEX_PNFT_LIFECYC
|
|||||||
La campagne escrow prépare un NFT classique parent et un token fungible attribut, puis exécute un cycle `TokenOwner` strictement contrôlé. Elle crée le PDA escrow, crée son ATA SPL classique pour le mint attribut, y dépose exactement une unité brute, transfère cette unité vers l’ATA de l’opérateur puis ferme le compte escrow.
|
La campagne escrow prépare un NFT classique parent et un token fungible attribut, puis exécute un cycle `TokenOwner` strictement contrôlé. Elle crée le PDA escrow, crée son ATA SPL classique pour le mint attribut, y dépose exactement une unité brute, transfère cette unité vers l’ATA de l’opérateur puis ferme le compte escrow.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
KB_DEVNET_METAPLEX_ESCROW_CAMPAIGN_TEST=1 \
|
KS_DEVNET_METAPLEX_ESCROW_CAMPAIGN_TEST=1 \
|
||||||
KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
|
KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
|
||||||
KB_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
|
KS_SECRET_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
|
||||||
cargo test -p ks-pipeline-demo-scenarios \
|
cargo test -p ks-pipeline-demo-scenarios \
|
||||||
optional_devnet_metaplex_escrow_campaign_from_env \
|
optional_devnet_metaplex_escrow_campaign_from_env \
|
||||||
-- --nocapture
|
-- --nocapture
|
||||||
@@ -456,9 +456,9 @@ Une exécution qualifiante doit produire `METAPLEX_ESCROW_FIXTURE`, deux lignes
|
|||||||
La campagne `maintenance_campaign` ferme les opérations courantes qui ne relèvent pas des parcours précédents. Elle crée un NFT classique frais, soumet réellement `Update` avec la transition bornée `primary_sale_happened: false -> true`, puis traite les surfaces non qualifiables positivement avec des probes **simulation-only**. Une simulation négative n'autorise jamais une soumission.
|
La campagne `maintenance_campaign` ferme les opérations courantes qui ne relèvent pas des parcours précédents. Elle crée un NFT classique frais, soumet réellement `Update` avec la transition bornée `primary_sale_happened: false -> true`, puis traite les surfaces non qualifiables positivement avec des probes **simulation-only**. Une simulation négative n'autorise jamais une soumission.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
KB_DEVNET_METAPLEX_MAINTENANCE_CAMPAIGN_TEST=1 \
|
KS_DEVNET_METAPLEX_MAINTENANCE_CAMPAIGN_TEST=1 \
|
||||||
KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
|
KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
|
||||||
KB_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
|
KS_SECRET_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
|
||||||
cargo test -p ks-pipeline-demo-scenarios \
|
cargo test -p ks-pipeline-demo-scenarios \
|
||||||
optional_devnet_metaplex_maintenance_campaign_from_env \
|
optional_devnet_metaplex_maintenance_campaign_from_env \
|
||||||
-- --nocapture
|
-- --nocapture
|
||||||
@@ -484,9 +484,9 @@ Les cinq familles NFT, SFT, fungible, collection et pNFT sont confirmées. `Crea
|
|||||||
La surface courante `Use` est classée `unavailable` sur Devnet : la simulation exacte du discriminant 51 retourne `InvalidInstructionData` et aucune transaction n'est soumise. Le test opt-in reste utile comme contrôle de non-régression du runtime :
|
La surface courante `Use` est classée `unavailable` sur Devnet : la simulation exacte du discriminant 51 retourne `InvalidInstructionData` et aucune transaction n'est soumise. Le test opt-in reste utile comme contrôle de non-régression du runtime :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
KB_DEVNET_METAPLEX_USE_PROBE_TEST=1 \
|
KS_DEVNET_METAPLEX_USE_PROBE_TEST=1 \
|
||||||
KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
|
KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
|
||||||
KB_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
|
KS_SECRET_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
|
||||||
cargo test -p ks-pipeline-demo-scenarios \
|
cargo test -p ks-pipeline-demo-scenarios \
|
||||||
optional_devnet_metaplex_use_probe_from_env \
|
optional_devnet_metaplex_use_probe_from_env \
|
||||||
-- --nocapture
|
-- --nocapture
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/bin/ks_pipeline_demo_scenarios_cli.rs
|
// file: ks-pipeline-demo-scenarios/src/bin/ks_pipeline_demo_scenarios_cli.rs
|
||||||
// version: 2
|
// version: 3
|
||||||
|
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
#![deny(unreachable_pub)]
|
#![deny(unreachable_pub)]
|
||||||
@@ -84,21 +84,21 @@ fn parse_prepare_options(
|
|||||||
}
|
}
|
||||||
index += 2;
|
index += 2;
|
||||||
}
|
}
|
||||||
let rpc_url = match rpc_url.or_else(|| return std::env::var("KB_DEVNET_RPC_URL").ok()) {
|
let rpc_url = match rpc_url.or_else(|| return std::env::var("KS_DEVNET_RPC_URL").ok()) {
|
||||||
std::option::Option::Some(value) => value,
|
std::option::Option::Some(value) => value,
|
||||||
std::option::Option::None => {
|
std::option::Option::None => {
|
||||||
return std::result::Result::Err(ks_core::Error::config(
|
return std::result::Result::Err(ks_core::Error::config(
|
||||||
"missing --rpc-url or KB_DEVNET_RPC_URL",
|
"missing --rpc-url or KS_DEVNET_RPC_URL",
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let wallet_path = match wallet_path
|
let wallet_path = match wallet_path
|
||||||
.or_else(|| return std::env::var("KB_DEVNET_WALLET").ok().map(std::path::PathBuf::from))
|
.or_else(|| return std::env::var("KS_DEVNET_WALLET").ok().map(std::path::PathBuf::from))
|
||||||
{
|
{
|
||||||
std::option::Option::Some(value) => value,
|
std::option::Option::Some(value) => value,
|
||||||
std::option::Option::None => {
|
std::option::Option::None => {
|
||||||
return std::result::Result::Err(ks_core::Error::config(
|
return std::result::Result::Err(ks_core::Error::config(
|
||||||
"missing --wallet or KB_DEVNET_WALLET",
|
"missing --wallet or KS_DEVNET_WALLET",
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/environment.rs
|
// file: ks-pipeline-demo-scenarios/src/environment.rs
|
||||||
// version: 3
|
// version: 4
|
||||||
|
|
||||||
//! Environment initialization for opt-in demonstration scenarios.
|
//! Environment initialization for opt-in demonstration scenarios.
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ pub fn initialize_demo_scenario_environment(
|
|||||||
|
|
||||||
/// Resolves one compatible Devnet profile for demo scenarios.
|
/// Resolves one compatible Devnet profile for demo scenarios.
|
||||||
///
|
///
|
||||||
/// An explicit name has priority, followed by `KB_DEVNET_PROFILE`, then the
|
/// An explicit name has priority, followed by `KS_DEVNET_PROFILE`, then the
|
||||||
/// first compatible Devnet profile declared by the configuration.
|
/// first compatible Devnet profile declared by the configuration.
|
||||||
pub fn resolve_demo_devnet_profile(
|
pub fn resolve_demo_devnet_profile(
|
||||||
config: &ks_config::AppConfig,
|
config: &ks_config::AppConfig,
|
||||||
@@ -24,7 +24,7 @@ pub fn resolve_demo_devnet_profile(
|
|||||||
.map(std::string::ToString::to_string);
|
.map(std::string::ToString::to_string);
|
||||||
let selected_name = match explicit {
|
let selected_name = match explicit {
|
||||||
std::option::Option::Some(value) => std::option::Option::Some(value),
|
std::option::Option::Some(value) => std::option::Option::Some(value),
|
||||||
std::option::Option::None => std::env::var("KB_DEVNET_PROFILE")
|
std::option::Option::None => std::env::var("KS_DEVNET_PROFILE")
|
||||||
.ok()
|
.ok()
|
||||||
.map(|value| return value.trim().to_string())
|
.map(|value| return value.trim().to_string())
|
||||||
.filter(|value| return !value.is_empty()),
|
.filter(|value| return !value.is_empty()),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/collection_verify_campaign.rs
|
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/collection_verify_campaign.rs
|
||||||
// version: 2
|
// version: 3
|
||||||
|
|
||||||
//! Confirmed Devnet collection parent/member `Verify -> Unverify` campaign.
|
//! Confirmed Devnet collection parent/member `Verify -> Unverify` campaign.
|
||||||
|
|
||||||
@@ -627,23 +627,23 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_metaplex_collection_verify_campaign_from_env() {
|
async fn optional_devnet_metaplex_collection_verify_campaign_from_env() {
|
||||||
if std::env::var("KB_DEVNET_METAPLEX_COLLECTION_VERIFY_CAMPAIGN_TEST")
|
if std::env::var("KS_DEVNET_METAPLEX_COLLECTION_VERIFY_CAMPAIGN_TEST")
|
||||||
.ok()
|
.ok()
|
||||||
.as_deref()
|
.as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if std::env::var("KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref()
|
if std::env::var("KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
panic!("KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 is required for the spending campaign");
|
panic!("KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 is required for the spending campaign");
|
||||||
}
|
}
|
||||||
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
||||||
std::option::Option::Some(value) => value,
|
std::option::Option::Some(value) => value,
|
||||||
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
||||||
};
|
};
|
||||||
let config_path = match std::env::var("KB_DEVNET_CONFIG_PATH") {
|
let config_path = match std::env::var("KS_DEVNET_CONFIG_PATH") {
|
||||||
std::result::Result::Ok(value) => {
|
std::result::Result::Ok(value) => {
|
||||||
let path = std::path::PathBuf::from(value);
|
let path = std::path::PathBuf::from(value);
|
||||||
if path.is_absolute() { path } else { workspace_root.join(path) }
|
if path.is_absolute() { path } else { workspace_root.join(path) }
|
||||||
@@ -655,11 +655,11 @@ mod tests {
|
|||||||
workspace_root,
|
workspace_root,
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
||||||
let profile_name = std::env::var("KB_DEVNET_PROFILE").ok();
|
let profile_name = std::env::var("KS_DEVNET_PROFILE").ok();
|
||||||
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
||||||
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
||||||
let database_url = std::env::var("KB_POSTGRES_TEST_URL")
|
let database_url = std::env::var("KS_SECRET_POSTGRES_TEST_URL")
|
||||||
.unwrap_or_else(|error| panic!("KB_POSTGRES_TEST_URL is required: {error}"));
|
.unwrap_or_else(|error| panic!("KS_SECRET_POSTGRES_TEST_URL is required: {error}"));
|
||||||
profile.database.backend = "postgres".to_string();
|
profile.database.backend = "postgres".to_string();
|
||||||
profile.database.postgres.url = database_url;
|
profile.database.postgres.url = database_url;
|
||||||
let pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
let pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/create_mint_campaign.rs
|
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/create_mint_campaign.rs
|
||||||
// version: 10
|
// version: 11
|
||||||
|
|
||||||
//! Confirmed Devnet `Create -> Mint` campaign for one Metaplex asset family.
|
//! Confirmed Devnet `Create -> Mint` campaign for one Metaplex asset family.
|
||||||
|
|
||||||
@@ -669,7 +669,7 @@ mod tests {
|
|||||||
"fungible" => crate::MetaplexTokenMetadataAssetFamily::Fungible,
|
"fungible" => crate::MetaplexTokenMetadataAssetFamily::Fungible,
|
||||||
"collection" => crate::MetaplexTokenMetadataAssetFamily::Collection,
|
"collection" => crate::MetaplexTokenMetadataAssetFamily::Collection,
|
||||||
"programmable_nft" | "pnft" => crate::MetaplexTokenMetadataAssetFamily::ProgrammableNft,
|
"programmable_nft" | "pnft" => crate::MetaplexTokenMetadataAssetFamily::ProgrammableNft,
|
||||||
_ => panic!("unsupported KB_DEVNET_METAPLEX_CREATE_MINT_FAMILY `{value}`"),
|
_ => panic!("unsupported KS_DEVNET_METAPLEX_CREATE_MINT_FAMILY `{value}`"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -794,21 +794,21 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_metaplex_create_mint_campaign_from_env() {
|
async fn optional_devnet_metaplex_create_mint_campaign_from_env() {
|
||||||
if std::env::var("KB_DEVNET_METAPLEX_CREATE_MINT_CAMPAIGN_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_METAPLEX_CREATE_MINT_CAMPAIGN_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if std::env::var("KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref()
|
if std::env::var("KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
panic!("KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 is required for the spending campaign");
|
panic!("KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 is required for the spending campaign");
|
||||||
}
|
}
|
||||||
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
||||||
std::option::Option::Some(value) => value,
|
std::option::Option::Some(value) => value,
|
||||||
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
||||||
};
|
};
|
||||||
let config_path = match std::env::var("KB_DEVNET_CONFIG_PATH") {
|
let config_path = match std::env::var("KS_DEVNET_CONFIG_PATH") {
|
||||||
std::result::Result::Ok(value) => {
|
std::result::Result::Ok(value) => {
|
||||||
let path = std::path::PathBuf::from(value);
|
let path = std::path::PathBuf::from(value);
|
||||||
if path.is_absolute() { path } else { workspace_root.join(path) }
|
if path.is_absolute() { path } else { workspace_root.join(path) }
|
||||||
@@ -820,11 +820,11 @@ mod tests {
|
|||||||
workspace_root,
|
workspace_root,
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
||||||
let profile_name = std::env::var("KB_DEVNET_PROFILE").ok();
|
let profile_name = std::env::var("KS_DEVNET_PROFILE").ok();
|
||||||
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
||||||
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
||||||
let database_url = std::env::var("KB_POSTGRES_TEST_URL")
|
let database_url = std::env::var("KS_SECRET_POSTGRES_TEST_URL")
|
||||||
.unwrap_or_else(|error| panic!("KB_POSTGRES_TEST_URL is required: {error}"));
|
.unwrap_or_else(|error| panic!("KS_SECRET_POSTGRES_TEST_URL is required: {error}"));
|
||||||
profile.database.backend = "postgres".to_string();
|
profile.database.backend = "postgres".to_string();
|
||||||
profile.database.postgres.url = database_url;
|
profile.database.postgres.url = database_url;
|
||||||
let pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
let pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
||||||
@@ -848,7 +848,7 @@ mod tests {
|
|||||||
} else {
|
} else {
|
||||||
workspace_root.join(configured_wallet_dir)
|
workspace_root.join(configured_wallet_dir)
|
||||||
};
|
};
|
||||||
let family = std::env::var("KB_DEVNET_METAPLEX_CREATE_MINT_FAMILY")
|
let family = std::env::var("KS_DEVNET_METAPLEX_CREATE_MINT_FAMILY")
|
||||||
.map(|value| return family_from_env(value.as_str()))
|
.map(|value| return family_from_env(value.as_str()))
|
||||||
.unwrap_or(crate::MetaplexTokenMetadataAssetFamily::Nft);
|
.unwrap_or(crate::MetaplexTokenMetadataAssetFamily::Nft);
|
||||||
let options = crate::MetaplexCreateFixturePreparationOptions::new(wallet_dir)
|
let options = crate::MetaplexCreateFixturePreparationOptions::new(wallet_dir)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/devnet_execution.rs
|
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/devnet_execution.rs
|
||||||
// version: 18
|
// version: 19
|
||||||
|
|
||||||
//! Real Devnet simulation and submission for current Metaplex Token Metadata operations.
|
//! Real Devnet simulation and submission for current Metaplex Token Metadata operations.
|
||||||
|
|
||||||
@@ -1403,29 +1403,29 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_current_operation_from_env() {
|
async fn optional_devnet_current_operation_from_env() {
|
||||||
if std::env::var("KB_DEVNET_METAPLEX_EXECUTION_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_METAPLEX_EXECUTION_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let operation_json = match std::env::var("KB_DEVNET_METAPLEX_OPERATION_JSON") {
|
let operation_json = match std::env::var("KS_DEVNET_METAPLEX_OPERATION_JSON") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
panic!("KB_DEVNET_METAPLEX_OPERATION_JSON is required: {error}");
|
panic!("KS_DEVNET_METAPLEX_OPERATION_JSON is required: {error}");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let mut profile = example_devnet_profile();
|
let mut profile = example_devnet_profile();
|
||||||
if let std::result::Result::Ok(directory) = std::env::var("KB_DEVNET_WALLET_DIR") {
|
if let std::result::Result::Ok(directory) = std::env::var("KS_DEVNET_WALLET_DIR") {
|
||||||
profile.wallet.wallet_dir = directory;
|
profile.wallet.wallet_dir = directory;
|
||||||
}
|
}
|
||||||
let pool = match ks_onchain_transport::HttpEndpointPool::from_profile(&profile) {
|
let pool = match ks_onchain_transport::HttpEndpointPool::from_profile(&profile) {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => panic!("HTTP pool creation failed: {error}"),
|
std::result::Result::Err(error) => panic!("HTTP pool creation failed: {error}"),
|
||||||
};
|
};
|
||||||
let database_url = match std::env::var("KB_POSTGRES_TEST_URL") {
|
let database_url = match std::env::var("KS_SECRET_POSTGRES_TEST_URL") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
panic!("KB_POSTGRES_TEST_URL is required for Metaplex execution: {error}")
|
panic!("KS_SECRET_POSTGRES_TEST_URL is required for Metaplex execution: {error}")
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let store_options = match ks_store::PostgresStoreOptions::new(database_url, 5, 5_000, false)
|
let store_options = match ks_store::PostgresStoreOptions::new(database_url, 5, 5_000, false)
|
||||||
@@ -1455,16 +1455,16 @@ mod tests {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
request.preflight_reads =
|
request.preflight_reads =
|
||||||
optional_stateful_reads_from_env("KB_DEVNET_METAPLEX_PREFLIGHT_READS_JSON");
|
optional_stateful_reads_from_env("KS_DEVNET_METAPLEX_PREFLIGHT_READS_JSON");
|
||||||
request.postcondition_reads =
|
request.postcondition_reads =
|
||||||
optional_stateful_reads_from_env("KB_DEVNET_METAPLEX_POSTCONDITION_READS_JSON");
|
optional_stateful_reads_from_env("KS_DEVNET_METAPLEX_POSTCONDITION_READS_JSON");
|
||||||
request.submit = std::env::var("KB_DEVNET_METAPLEX_SUBMIT").ok().as_deref()
|
request.submit = std::env::var("KS_DEVNET_METAPLEX_SUBMIT").ok().as_deref()
|
||||||
== std::option::Option::Some("1");
|
== std::option::Option::Some("1");
|
||||||
request.operator_confirmed = request.submit
|
request.operator_confirmed = request.submit
|
||||||
&& std::env::var("KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref()
|
&& std::env::var("KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref()
|
||||||
== std::option::Option::Some("1");
|
== std::option::Option::Some("1");
|
||||||
request.materialize_after_confirmation = request.submit
|
request.materialize_after_confirmation = request.submit
|
||||||
&& std::env::var("KB_DEVNET_METAPLEX_MATERIALIZE_AFTER_CONFIRMATION")
|
&& std::env::var("KS_DEVNET_METAPLEX_MATERIALIZE_AFTER_CONFIRMATION")
|
||||||
.ok()
|
.ok()
|
||||||
.as_deref()
|
.as_deref()
|
||||||
== std::option::Option::Some("1");
|
== std::option::Option::Some("1");
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/escrow_campaign.rs
|
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/escrow_campaign.rs
|
||||||
// version: 2
|
// version: 3
|
||||||
|
|
||||||
//! Confirmed Devnet Token Owned Escrow campaign for current Metaplex escrow operations.
|
//! Confirmed Devnet Token Owned Escrow campaign for current Metaplex escrow operations.
|
||||||
|
|
||||||
@@ -954,21 +954,21 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_metaplex_escrow_campaign_from_env() {
|
async fn optional_devnet_metaplex_escrow_campaign_from_env() {
|
||||||
if std::env::var("KB_DEVNET_METAPLEX_ESCROW_CAMPAIGN_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_METAPLEX_ESCROW_CAMPAIGN_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
std::env::var("KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref(),
|
std::env::var("KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref(),
|
||||||
std::option::Option::Some("1"),
|
std::option::Option::Some("1"),
|
||||||
"set KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 before the escrow campaign"
|
"set KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 before the escrow campaign"
|
||||||
);
|
);
|
||||||
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
||||||
std::option::Option::Some(value) => value,
|
std::option::Option::Some(value) => value,
|
||||||
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
||||||
};
|
};
|
||||||
let config_path = match std::env::var("KB_DEVNET_CONFIG_PATH") {
|
let config_path = match std::env::var("KS_DEVNET_CONFIG_PATH") {
|
||||||
std::result::Result::Ok(value) => {
|
std::result::Result::Ok(value) => {
|
||||||
let path = std::path::PathBuf::from(value);
|
let path = std::path::PathBuf::from(value);
|
||||||
if path.is_absolute() { path } else { workspace_root.join(path) }
|
if path.is_absolute() { path } else { workspace_root.join(path) }
|
||||||
@@ -980,11 +980,11 @@ mod tests {
|
|||||||
workspace_root,
|
workspace_root,
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
||||||
let profile_name = std::env::var("KB_DEVNET_PROFILE").ok();
|
let profile_name = std::env::var("KS_DEVNET_PROFILE").ok();
|
||||||
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
||||||
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
||||||
let database_url = std::env::var("KB_POSTGRES_TEST_URL")
|
let database_url = std::env::var("KS_SECRET_POSTGRES_TEST_URL")
|
||||||
.unwrap_or_else(|error| panic!("KB_POSTGRES_TEST_URL is required: {error}"));
|
.unwrap_or_else(|error| panic!("KS_SECRET_POSTGRES_TEST_URL is required: {error}"));
|
||||||
profile.database.backend = "postgres".to_string();
|
profile.database.backend = "postgres".to_string();
|
||||||
profile.database.postgres.url = database_url;
|
profile.database.postgres.url = database_url;
|
||||||
let http_pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
let http_pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/maintenance_campaign.rs
|
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/maintenance_campaign.rs
|
||||||
// version: 4
|
// version: 5
|
||||||
|
|
||||||
//! Final bounded Devnet qualification campaign for current Metaplex maintenance operations.
|
//! Final bounded Devnet qualification campaign for current Metaplex maintenance operations.
|
||||||
|
|
||||||
@@ -558,21 +558,21 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_metaplex_maintenance_campaign_from_env() {
|
async fn optional_devnet_metaplex_maintenance_campaign_from_env() {
|
||||||
if std::env::var("KB_DEVNET_METAPLEX_MAINTENANCE_CAMPAIGN_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_METAPLEX_MAINTENANCE_CAMPAIGN_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
std::env::var("KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref(),
|
std::env::var("KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref(),
|
||||||
std::option::Option::Some("1"),
|
std::option::Option::Some("1"),
|
||||||
"set KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 before the maintenance campaign"
|
"set KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 before the maintenance campaign"
|
||||||
);
|
);
|
||||||
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
||||||
std::option::Option::Some(value) => value,
|
std::option::Option::Some(value) => value,
|
||||||
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
||||||
};
|
};
|
||||||
let config_path = match std::env::var("KB_DEVNET_CONFIG_PATH") {
|
let config_path = match std::env::var("KS_DEVNET_CONFIG_PATH") {
|
||||||
std::result::Result::Ok(value) => {
|
std::result::Result::Ok(value) => {
|
||||||
let path = std::path::PathBuf::from(value);
|
let path = std::path::PathBuf::from(value);
|
||||||
if path.is_absolute() { path } else { workspace_root.join(path) }
|
if path.is_absolute() { path } else { workspace_root.join(path) }
|
||||||
@@ -584,11 +584,11 @@ mod tests {
|
|||||||
workspace_root,
|
workspace_root,
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
||||||
let profile_name = std::env::var("KB_DEVNET_PROFILE").ok();
|
let profile_name = std::env::var("KS_DEVNET_PROFILE").ok();
|
||||||
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
||||||
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
||||||
let database_url = std::env::var("KB_POSTGRES_TEST_URL")
|
let database_url = std::env::var("KS_SECRET_POSTGRES_TEST_URL")
|
||||||
.unwrap_or_else(|error| panic!("KB_POSTGRES_TEST_URL is required: {error}"));
|
.unwrap_or_else(|error| panic!("KS_SECRET_POSTGRES_TEST_URL is required: {error}"));
|
||||||
profile.database.backend = "postgres".to_string();
|
profile.database.backend = "postgres".to_string();
|
||||||
profile.database.postgres.url = database_url;
|
profile.database.postgres.url = database_url;
|
||||||
let http_pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
let http_pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/pnft_lifecycle_campaign.rs
|
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/pnft_lifecycle_campaign.rs
|
||||||
// version: 4
|
// version: 5
|
||||||
|
|
||||||
//! Confirmed Devnet pNFT delegate, lock, unlock, revoke and transfer campaign.
|
//! Confirmed Devnet pNFT delegate, lock, unlock, revoke and transfer campaign.
|
||||||
|
|
||||||
@@ -1052,21 +1052,21 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_metaplex_pnft_lifecycle_campaign_from_env() {
|
async fn optional_devnet_metaplex_pnft_lifecycle_campaign_from_env() {
|
||||||
if std::env::var("KB_DEVNET_METAPLEX_PNFT_LIFECYCLE_CAMPAIGN_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_METAPLEX_PNFT_LIFECYCLE_CAMPAIGN_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
std::env::var("KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref(),
|
std::env::var("KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref(),
|
||||||
std::option::Option::Some("1"),
|
std::option::Option::Some("1"),
|
||||||
"set KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 before submitting the pNFT lifecycle campaign"
|
"set KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 before submitting the pNFT lifecycle campaign"
|
||||||
);
|
);
|
||||||
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
||||||
std::option::Option::Some(value) => value,
|
std::option::Option::Some(value) => value,
|
||||||
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
||||||
};
|
};
|
||||||
let config_path = match std::env::var("KB_DEVNET_CONFIG_PATH") {
|
let config_path = match std::env::var("KS_DEVNET_CONFIG_PATH") {
|
||||||
std::result::Result::Ok(value) => {
|
std::result::Result::Ok(value) => {
|
||||||
let path = std::path::PathBuf::from(value);
|
let path = std::path::PathBuf::from(value);
|
||||||
if path.is_absolute() { path } else { workspace_root.join(path) }
|
if path.is_absolute() { path } else { workspace_root.join(path) }
|
||||||
@@ -1078,11 +1078,11 @@ mod tests {
|
|||||||
workspace_root,
|
workspace_root,
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
||||||
let profile_name = std::env::var("KB_DEVNET_PROFILE").ok();
|
let profile_name = std::env::var("KS_DEVNET_PROFILE").ok();
|
||||||
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
||||||
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
||||||
let database_url = std::env::var("KB_POSTGRES_TEST_URL")
|
let database_url = std::env::var("KS_SECRET_POSTGRES_TEST_URL")
|
||||||
.unwrap_or_else(|error| panic!("KB_POSTGRES_TEST_URL is required: {error}"));
|
.unwrap_or_else(|error| panic!("KS_SECRET_POSTGRES_TEST_URL is required: {error}"));
|
||||||
profile.database.backend = "postgres".to_string();
|
profile.database.backend = "postgres".to_string();
|
||||||
profile.database.postgres.url = database_url;
|
profile.database.postgres.url = database_url;
|
||||||
let http_pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
let http_pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/print_burn_campaign.rs
|
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/print_burn_campaign.rs
|
||||||
// version: 5
|
// version: 6
|
||||||
|
|
||||||
//! Devnet printable master NFT `Print -> Burn` campaign.
|
//! Devnet printable master NFT `Print -> Burn` campaign.
|
||||||
|
|
||||||
@@ -1161,21 +1161,21 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_metaplex_print_burn_campaign_from_env() {
|
async fn optional_devnet_metaplex_print_burn_campaign_from_env() {
|
||||||
if std::env::var("KB_DEVNET_METAPLEX_PRINT_BURN_CAMPAIGN_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_METAPLEX_PRINT_BURN_CAMPAIGN_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if std::env::var("KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref()
|
if std::env::var("KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
panic!("KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 is required for the spending campaign");
|
panic!("KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 is required for the spending campaign");
|
||||||
}
|
}
|
||||||
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
||||||
std::option::Option::Some(value) => value,
|
std::option::Option::Some(value) => value,
|
||||||
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
||||||
};
|
};
|
||||||
let config_path = match std::env::var("KB_DEVNET_CONFIG_PATH") {
|
let config_path = match std::env::var("KS_DEVNET_CONFIG_PATH") {
|
||||||
std::result::Result::Ok(value) => {
|
std::result::Result::Ok(value) => {
|
||||||
let path = std::path::PathBuf::from(value);
|
let path = std::path::PathBuf::from(value);
|
||||||
if path.is_absolute() { path } else { workspace_root.join(path) }
|
if path.is_absolute() { path } else { workspace_root.join(path) }
|
||||||
@@ -1187,11 +1187,11 @@ mod tests {
|
|||||||
workspace_root,
|
workspace_root,
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
||||||
let profile_name = std::env::var("KB_DEVNET_PROFILE").ok();
|
let profile_name = std::env::var("KS_DEVNET_PROFILE").ok();
|
||||||
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
||||||
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
||||||
let database_url = std::env::var("KB_POSTGRES_TEST_URL")
|
let database_url = std::env::var("KS_SECRET_POSTGRES_TEST_URL")
|
||||||
.unwrap_or_else(|error| panic!("KB_POSTGRES_TEST_URL is required: {error}"));
|
.unwrap_or_else(|error| panic!("KS_SECRET_POSTGRES_TEST_URL is required: {error}"));
|
||||||
profile.database.backend = "postgres".to_string();
|
profile.database.backend = "postgres".to_string();
|
||||||
profile.database.postgres.url = database_url;
|
profile.database.postgres.url = database_url;
|
||||||
let pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
let pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/use_campaign.rs
|
// file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/use_campaign.rs
|
||||||
// version: 2
|
// version: 3
|
||||||
|
|
||||||
//! Bounded Devnet availability probe for the current Metaplex `Use` surface.
|
//! Bounded Devnet availability probe for the current Metaplex `Use` surface.
|
||||||
|
|
||||||
@@ -406,21 +406,21 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_metaplex_use_probe_from_env() {
|
async fn optional_devnet_metaplex_use_probe_from_env() {
|
||||||
if std::env::var("KB_DEVNET_METAPLEX_USE_PROBE_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_METAPLEX_USE_PROBE_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
std::env::var("KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref(),
|
std::env::var("KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED").ok().as_deref(),
|
||||||
std::option::Option::Some("1"),
|
std::option::Option::Some("1"),
|
||||||
"set KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 before submitting an accepted Use probe"
|
"set KS_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 before submitting an accepted Use probe"
|
||||||
);
|
);
|
||||||
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
||||||
std::option::Option::Some(value) => value,
|
std::option::Option::Some(value) => value,
|
||||||
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
||||||
};
|
};
|
||||||
let config_path = match std::env::var("KB_DEVNET_CONFIG_PATH") {
|
let config_path = match std::env::var("KS_DEVNET_CONFIG_PATH") {
|
||||||
std::result::Result::Ok(value) => {
|
std::result::Result::Ok(value) => {
|
||||||
let path = std::path::PathBuf::from(value);
|
let path = std::path::PathBuf::from(value);
|
||||||
if path.is_absolute() { path } else { workspace_root.join(path) }
|
if path.is_absolute() { path } else { workspace_root.join(path) }
|
||||||
@@ -432,11 +432,11 @@ mod tests {
|
|||||||
workspace_root,
|
workspace_root,
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
||||||
let profile_name = std::env::var("KB_DEVNET_PROFILE").ok();
|
let profile_name = std::env::var("KS_DEVNET_PROFILE").ok();
|
||||||
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
||||||
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
||||||
let database_url = std::env::var("KB_POSTGRES_TEST_URL")
|
let database_url = std::env::var("KS_SECRET_POSTGRES_TEST_URL")
|
||||||
.unwrap_or_else(|error| panic!("KB_POSTGRES_TEST_URL is required: {error}"));
|
.unwrap_or_else(|error| panic!("KS_SECRET_POSTGRES_TEST_URL is required: {error}"));
|
||||||
profile.database.backend = "postgres".to_string();
|
profile.database.backend = "postgres".to_string();
|
||||||
profile.database.postgres.url = database_url;
|
profile.database.postgres.url = database_url;
|
||||||
let http_pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
let http_pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/solana.rs
|
// file: ks-pipeline-demo-scenarios/src/solana.rs
|
||||||
// version: 12
|
// version: 13
|
||||||
|
|
||||||
//! Devnet Solana execution orchestration with canonical post-validation.
|
//! Devnet Solana execution orchestration with canonical post-validation.
|
||||||
|
|
||||||
@@ -1332,21 +1332,21 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_system_transfer_from_env() {
|
async fn optional_devnet_system_transfer_from_env() {
|
||||||
if std::env::var("KB_DEVNET_EXECUTION_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_EXECUTION_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let database_url = match std::env::var("KB_POSTGRES_TEST_URL") {
|
let database_url = match std::env::var("KS_SECRET_POSTGRES_TEST_URL") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
panic!("KB_POSTGRES_TEST_URL is required: {error}");
|
panic!("KS_SECRET_POSTGRES_TEST_URL is required: {error}");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let mut profile = example_devnet_profile();
|
let mut profile = example_devnet_profile();
|
||||||
profile.database.backend = "postgres".to_string();
|
profile.database.backend = "postgres".to_string();
|
||||||
profile.database.postgres.url = database_url;
|
profile.database.postgres.url = database_url;
|
||||||
if let std::result::Result::Ok(directory) = std::env::var("KB_DEVNET_WALLET_DIR") {
|
if let std::result::Result::Ok(directory) = std::env::var("KS_DEVNET_WALLET_DIR") {
|
||||||
profile.wallet.wallet_dir = directory;
|
profile.wallet.wallet_dir = directory;
|
||||||
}
|
}
|
||||||
let pool = match ks_onchain_transport::HttpEndpointPool::from_profile(&profile) {
|
let pool = match ks_onchain_transport::HttpEndpointPool::from_profile(&profile) {
|
||||||
@@ -1374,11 +1374,11 @@ mod tests {
|
|||||||
std::result::Result::Err(error) => panic!("recipient alias failed: {error}"),
|
std::result::Result::Err(error) => panic!("recipient alias failed: {error}"),
|
||||||
};
|
};
|
||||||
let recipient_wallet = ks_wallet::TemporaryWallet::generate(recipient_alias);
|
let recipient_wallet = ks_wallet::TemporaryWallet::generate(recipient_alias);
|
||||||
let transfer_lamports = std::env::var("KB_DEVNET_TRANSFER_LAMPORTS")
|
let transfer_lamports = std::env::var("KS_DEVNET_TRANSFER_LAMPORTS")
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|value| return value.parse::<u64>().ok())
|
.and_then(|value| return value.parse::<u64>().ok())
|
||||||
.unwrap_or(1_000_000);
|
.unwrap_or(1_000_000);
|
||||||
let airdrop_lamports = std::env::var("KB_DEVNET_AIRDROP_LAMPORTS")
|
let airdrop_lamports = std::env::var("KS_DEVNET_AIRDROP_LAMPORTS")
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|value| return value.parse::<u64>().ok())
|
.and_then(|value| return value.parse::<u64>().ok())
|
||||||
.unwrap_or(100_000_000);
|
.unwrap_or(100_000_000);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/spl/associated_token_account.rs
|
// file: ks-pipeline-demo-scenarios/src/spl/associated_token_account.rs
|
||||||
// version: 11
|
// version: 12
|
||||||
|
|
||||||
//! Devnet ATA execution with stateful and canonical post-validation.
|
//! Devnet ATA execution with stateful and canonical post-validation.
|
||||||
|
|
||||||
@@ -1071,14 +1071,14 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_operation_from_env() {
|
async fn optional_devnet_operation_from_env() {
|
||||||
if std::env::var("KB_DEVNET_SPL_ATA_EXECUTION_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_SPL_ATA_EXECUTION_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let operation_code = std::env::var("KB_DEVNET_SPL_ATA_OPERATION")
|
let operation_code = std::env::var("KS_DEVNET_SPL_ATA_OPERATION")
|
||||||
.unwrap_or_else(|_| return "create_idempotent".to_string());
|
.unwrap_or_else(|_| return "create_idempotent".to_string());
|
||||||
let token_program = match std::env::var("KB_DEVNET_SPL_ATA_TOKEN_PROGRAM").ok().as_deref() {
|
let token_program = match std::env::var("KS_DEVNET_SPL_ATA_TOKEN_PROGRAM").ok().as_deref() {
|
||||||
std::option::Option::Some("token_2022") => {
|
std::option::Option::Some("token_2022") => {
|
||||||
ks_lib::ExSplAssociatedTokenProgram::Token2022
|
ks_lib::ExSplAssociatedTokenProgram::Token2022
|
||||||
},
|
},
|
||||||
@@ -1087,7 +1087,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
std::option::Option::Some(value) => panic!("unsupported Token Program {value}"),
|
std::option::Option::Some(value) => panic!("unsupported Token Program {value}"),
|
||||||
};
|
};
|
||||||
let submit = std::env::var("KB_DEVNET_SPL_ATA_SUBMIT").ok().as_deref()
|
let submit = std::env::var("KS_DEVNET_SPL_ATA_SUBMIT").ok().as_deref()
|
||||||
== std::option::Option::Some("1");
|
== std::option::Option::Some("1");
|
||||||
let profile = example_devnet_profile();
|
let profile = example_devnet_profile();
|
||||||
let workspace_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
let workspace_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||||
@@ -1101,16 +1101,16 @@ mod tests {
|
|||||||
let operation = match operation_code.as_str() {
|
let operation = match operation_code.as_str() {
|
||||||
"create_idempotent" => ks_lib::ExSplAssociatedTokenAccountOperation::CreateIdempotent {
|
"create_idempotent" => ks_lib::ExSplAssociatedTokenAccountOperation::CreateIdempotent {
|
||||||
wallet_owner: ks_lib::MdPubkey(wallet_pubkey),
|
wallet_owner: ks_lib::MdPubkey(wallet_pubkey),
|
||||||
mint: ks_lib::MdPubkey(required_environment_value("KB_DEVNET_SPL_ATA_MINT")),
|
mint: ks_lib::MdPubkey(required_environment_value("KS_DEVNET_SPL_ATA_MINT")),
|
||||||
token_program,
|
token_program,
|
||||||
},
|
},
|
||||||
"recover_nested" => ks_lib::ExSplAssociatedTokenAccountOperation::RecoverNested {
|
"recover_nested" => ks_lib::ExSplAssociatedTokenAccountOperation::RecoverNested {
|
||||||
wallet_owner: ks_lib::MdPubkey(wallet_pubkey),
|
wallet_owner: ks_lib::MdPubkey(wallet_pubkey),
|
||||||
owner_mint: ks_lib::MdPubkey(required_environment_value(
|
owner_mint: ks_lib::MdPubkey(required_environment_value(
|
||||||
"KB_DEVNET_SPL_ATA_OWNER_MINT",
|
"KS_DEVNET_SPL_ATA_OWNER_MINT",
|
||||||
)),
|
)),
|
||||||
nested_mint: ks_lib::MdPubkey(required_environment_value(
|
nested_mint: ks_lib::MdPubkey(required_environment_value(
|
||||||
"KB_DEVNET_SPL_ATA_NESTED_MINT",
|
"KS_DEVNET_SPL_ATA_NESTED_MINT",
|
||||||
)),
|
)),
|
||||||
token_program,
|
token_program,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/spl/memo.rs
|
// file: ks-pipeline-demo-scenarios/src/spl/memo.rs
|
||||||
// version: 7
|
// version: 8
|
||||||
|
|
||||||
//! Devnet SPL Memo v4 execution with canonical post-validation.
|
//! Devnet SPL Memo v4 execution with canonical post-validation.
|
||||||
|
|
||||||
@@ -810,21 +810,21 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_memo_execution_from_env() {
|
async fn optional_devnet_memo_execution_from_env() {
|
||||||
if std::env::var("KB_DEVNET_MEMO_EXECUTION_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_MEMO_EXECUTION_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let database_url = match std::env::var("KB_POSTGRES_TEST_URL") {
|
let database_url = match std::env::var("KS_SECRET_POSTGRES_TEST_URL") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
panic!("KB_POSTGRES_TEST_URL is required: {error}");
|
panic!("KS_SECRET_POSTGRES_TEST_URL is required: {error}");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let mut profile = example_devnet_profile();
|
let mut profile = example_devnet_profile();
|
||||||
profile.database.backend = "postgres".to_string();
|
profile.database.backend = "postgres".to_string();
|
||||||
profile.database.postgres.url = database_url;
|
profile.database.postgres.url = database_url;
|
||||||
if let std::result::Result::Ok(directory) = std::env::var("KB_DEVNET_WALLET_DIR") {
|
if let std::result::Result::Ok(directory) = std::env::var("KS_DEVNET_WALLET_DIR") {
|
||||||
profile.wallet.wallet_dir = directory;
|
profile.wallet.wallet_dir = directory;
|
||||||
}
|
}
|
||||||
let pool = match ks_onchain_transport::HttpEndpointPool::from_profile(&profile) {
|
let pool = match ks_onchain_transport::HttpEndpointPool::from_profile(&profile) {
|
||||||
@@ -852,7 +852,7 @@ mod tests {
|
|||||||
format!("khadhroony-bot3 memo validation {}", uuid::Uuid::new_v4()),
|
format!("khadhroony-bot3 memo validation {}", uuid::Uuid::new_v4()),
|
||||||
);
|
);
|
||||||
request.post_validation_max_retries = 20;
|
request.post_validation_max_retries = 20;
|
||||||
if std::env::var("KB_DEVNET_MEMO_SUBMIT").ok().as_deref() == std::option::Option::Some("1")
|
if std::env::var("KS_DEVNET_MEMO_SUBMIT").ok().as_deref() == std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
request.submit = true;
|
request.submit = true;
|
||||||
request.operator_confirmed = true;
|
request.operator_confirmed = true;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/spl/token/execution.rs
|
// file: ks-pipeline-demo-scenarios/src/spl/token/execution.rs
|
||||||
// version: 11
|
// version: 12
|
||||||
|
|
||||||
//! Devnet classic SPL Token execution with stateful and canonical post-validation.
|
//! Devnet classic SPL Token execution with stateful and canonical post-validation.
|
||||||
|
|
||||||
@@ -1071,28 +1071,28 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_checked_transfer_simulation_and_submission_from_env() {
|
async fn optional_devnet_checked_transfer_simulation_and_submission_from_env() {
|
||||||
if std::env::var("KB_DEVNET_SPL_TOKEN_EXECUTION_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_SPL_TOKEN_EXECUTION_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let source = required_pubkey_env("KB_DEVNET_SPL_TOKEN_SOURCE");
|
let source = required_pubkey_env("KS_DEVNET_SPL_TOKEN_SOURCE");
|
||||||
let mint = required_pubkey_env("KB_DEVNET_SPL_TOKEN_MINT");
|
let mint = required_pubkey_env("KS_DEVNET_SPL_TOKEN_MINT");
|
||||||
let destination = required_pubkey_env("KB_DEVNET_SPL_TOKEN_DESTINATION");
|
let destination = required_pubkey_env("KS_DEVNET_SPL_TOKEN_DESTINATION");
|
||||||
let authority = required_pubkey_env("KB_DEVNET_SPL_TOKEN_AUTHORITY");
|
let authority = required_pubkey_env("KS_DEVNET_SPL_TOKEN_AUTHORITY");
|
||||||
let decimals = match std::env::var("KB_DEVNET_SPL_TOKEN_DECIMALS") {
|
let decimals = match std::env::var("KS_DEVNET_SPL_TOKEN_DECIMALS") {
|
||||||
std::result::Result::Ok(value) => match value.parse::<u8>() {
|
std::result::Result::Ok(value) => match value.parse::<u8>() {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => panic!("invalid Token decimals: {error}"),
|
std::result::Result::Err(error) => panic!("invalid Token decimals: {error}"),
|
||||||
},
|
},
|
||||||
std::result::Result::Err(_) => 9,
|
std::result::Result::Err(_) => 9,
|
||||||
};
|
};
|
||||||
let amount = match std::env::var("KB_DEVNET_SPL_TOKEN_AMOUNT") {
|
let amount = match std::env::var("KS_DEVNET_SPL_TOKEN_AMOUNT") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(_) => "1".to_string(),
|
std::result::Result::Err(_) => "1".to_string(),
|
||||||
};
|
};
|
||||||
let mut profile = example_devnet_profile();
|
let mut profile = example_devnet_profile();
|
||||||
if let std::result::Result::Ok(directory) = std::env::var("KB_DEVNET_WALLET_DIR") {
|
if let std::result::Result::Ok(directory) = std::env::var("KS_DEVNET_WALLET_DIR") {
|
||||||
profile.wallet.wallet_dir = directory;
|
profile.wallet.wallet_dir = directory;
|
||||||
}
|
}
|
||||||
let pool = match ks_onchain_transport::HttpEndpointPool::from_profile(&profile) {
|
let pool = match ks_onchain_transport::HttpEndpointPool::from_profile(&profile) {
|
||||||
@@ -1119,7 +1119,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if std::env::var("KB_DEVNET_SPL_TOKEN_SUBMIT").ok().as_deref()
|
if std::env::var("KS_DEVNET_SPL_TOKEN_SUBMIT").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
let summary = match crate::simulate_devnet_spl_token(
|
let summary = match crate::simulate_devnet_spl_token(
|
||||||
@@ -1146,10 +1146,10 @@ mod tests {
|
|||||||
request.submit = true;
|
request.submit = true;
|
||||||
request.operator_confirmed = true;
|
request.operator_confirmed = true;
|
||||||
request.post_validation_max_retries = 20;
|
request.post_validation_max_retries = 20;
|
||||||
let database_url = match std::env::var("KB_POSTGRES_TEST_URL") {
|
let database_url = match std::env::var("KS_SECRET_POSTGRES_TEST_URL") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
panic!("KB_POSTGRES_TEST_URL is required for submission: {error}");
|
panic!("KS_SECRET_POSTGRES_TEST_URL is required for submission: {error}");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
profile.database.backend = "postgres".to_string();
|
profile.database.backend = "postgres".to_string();
|
||||||
@@ -1244,17 +1244,17 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_recent_instruction_probe_from_env() {
|
async fn optional_devnet_recent_instruction_probe_from_env() {
|
||||||
if std::env::var("KB_DEVNET_SPL_TOKEN_RECENT_PROBE_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_SPL_TOKEN_RECENT_PROBE_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let source = required_pubkey_env("KB_DEVNET_SPL_TOKEN_SOURCE");
|
let source = required_pubkey_env("KS_DEVNET_SPL_TOKEN_SOURCE");
|
||||||
let mint = required_pubkey_env("KB_DEVNET_SPL_TOKEN_MINT");
|
let mint = required_pubkey_env("KS_DEVNET_SPL_TOKEN_MINT");
|
||||||
let destination = required_pubkey_env("KB_DEVNET_SPL_TOKEN_DESTINATION");
|
let destination = required_pubkey_env("KS_DEVNET_SPL_TOKEN_DESTINATION");
|
||||||
let authority = required_pubkey_env("KB_DEVNET_SPL_TOKEN_AUTHORITY");
|
let authority = required_pubkey_env("KS_DEVNET_SPL_TOKEN_AUTHORITY");
|
||||||
let native_account = required_pubkey_env("KB_DEVNET_SPL_TOKEN_NATIVE_ACCOUNT");
|
let native_account = required_pubkey_env("KS_DEVNET_SPL_TOKEN_NATIVE_ACCOUNT");
|
||||||
let decimals = match std::env::var("KB_DEVNET_SPL_TOKEN_DECIMALS") {
|
let decimals = match std::env::var("KS_DEVNET_SPL_TOKEN_DECIMALS") {
|
||||||
std::result::Result::Ok(value) => match value.parse::<u8>() {
|
std::result::Result::Ok(value) => match value.parse::<u8>() {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => panic!("invalid Token decimals: {error}"),
|
std::result::Result::Err(error) => panic!("invalid Token decimals: {error}"),
|
||||||
@@ -1262,7 +1262,7 @@ mod tests {
|
|||||||
std::result::Result::Err(_) => 9,
|
std::result::Result::Err(_) => 9,
|
||||||
};
|
};
|
||||||
let mut profile = example_devnet_profile();
|
let mut profile = example_devnet_profile();
|
||||||
if let std::result::Result::Ok(directory) = std::env::var("KB_DEVNET_WALLET_DIR") {
|
if let std::result::Result::Ok(directory) = std::env::var("KS_DEVNET_WALLET_DIR") {
|
||||||
profile.wallet.wallet_dir = directory;
|
profile.wallet.wallet_dir = directory;
|
||||||
}
|
}
|
||||||
let pool = match ks_onchain_transport::HttpEndpointPool::from_profile(&profile) {
|
let pool = match ks_onchain_transport::HttpEndpointPool::from_profile(&profile) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/spl/token/lifecycle.rs
|
// file: ks-pipeline-demo-scenarios/src/spl/token/lifecycle.rs
|
||||||
// version: 10
|
// version: 11
|
||||||
|
|
||||||
//! Controlled Devnet lifecycle for freshly prepared classic SPL Token accounts.
|
//! Controlled Devnet lifecycle for freshly prepared classic SPL Token accounts.
|
||||||
|
|
||||||
@@ -1500,24 +1500,24 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_controlled_lifecycle_from_env() {
|
async fn optional_devnet_controlled_lifecycle_from_env() {
|
||||||
if std::env::var("KB_DEVNET_SPL_TOKEN_LIFECYCLE_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_SPL_TOKEN_LIFECYCLE_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if std::env::var("KB_DEVNET_SPL_TOKEN_LIFECYCLE_SUBMIT").ok().as_deref()
|
if std::env::var("KS_DEVNET_SPL_TOKEN_LIFECYCLE_SUBMIT").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
panic!("controlled lifecycle requires KB_DEVNET_SPL_TOKEN_LIFECYCLE_SUBMIT=1");
|
panic!("controlled lifecycle requires KS_DEVNET_SPL_TOKEN_LIFECYCLE_SUBMIT=1");
|
||||||
}
|
}
|
||||||
let mut profile = example_devnet_profile();
|
let mut profile = example_devnet_profile();
|
||||||
if let std::result::Result::Ok(directory) = std::env::var("KB_DEVNET_WALLET_DIR") {
|
if let std::result::Result::Ok(directory) = std::env::var("KS_DEVNET_WALLET_DIR") {
|
||||||
profile.wallet.wallet_dir = directory;
|
profile.wallet.wallet_dir = directory;
|
||||||
}
|
}
|
||||||
let database_url = match std::env::var("KB_POSTGRES_TEST_URL") {
|
let database_url = match std::env::var("KS_SECRET_POSTGRES_TEST_URL") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
panic!("KB_POSTGRES_TEST_URL is required for lifecycle submission: {error}");
|
panic!("KS_SECRET_POSTGRES_TEST_URL is required for lifecycle submission: {error}");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
profile.database.backend = "postgres".to_string();
|
profile.database.backend = "postgres".to_string();
|
||||||
@@ -1547,7 +1547,7 @@ mod tests {
|
|||||||
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
||||||
};
|
};
|
||||||
let observer = LifecycleTestObserver;
|
let observer = LifecycleTestObserver;
|
||||||
let prepared_accounts = if std::env::var("KB_DEVNET_SPL_TOKEN_LIFECYCLE_PREPARE")
|
let prepared_accounts = if std::env::var("KS_DEVNET_SPL_TOKEN_LIFECYCLE_PREPARE")
|
||||||
.ok()
|
.ok()
|
||||||
.as_deref()
|
.as_deref()
|
||||||
== std::option::Option::Some("1")
|
== std::option::Option::Some("1")
|
||||||
@@ -1589,7 +1589,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
if prepared_accounts.is_some() {
|
if prepared_accounts.is_some() {
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(optional_u64_env(
|
tokio::time::sleep(std::time::Duration::from_millis(optional_u64_env(
|
||||||
"KB_DEVNET_SPL_TOKEN_LIFECYCLE_PREPARATION_SETTLE_DELAY_MS",
|
"KS_DEVNET_SPL_TOKEN_LIFECYCLE_PREPARATION_SETTLE_DELAY_MS",
|
||||||
10_000,
|
10_000,
|
||||||
)))
|
)))
|
||||||
.await;
|
.await;
|
||||||
@@ -1603,11 +1603,11 @@ mod tests {
|
|||||||
value.authority.clone(),
|
value.authority.clone(),
|
||||||
),
|
),
|
||||||
std::option::Option::None => (
|
std::option::Option::None => (
|
||||||
required_pubkey_env("KB_DEVNET_SPL_TOKEN_LIFECYCLE_MINT"),
|
required_pubkey_env("KS_DEVNET_SPL_TOKEN_LIFECYCLE_MINT"),
|
||||||
required_pubkey_env("KB_DEVNET_SPL_TOKEN_LIFECYCLE_SOURCE"),
|
required_pubkey_env("KS_DEVNET_SPL_TOKEN_LIFECYCLE_SOURCE"),
|
||||||
required_pubkey_env("KB_DEVNET_SPL_TOKEN_LIFECYCLE_DESTINATION"),
|
required_pubkey_env("KS_DEVNET_SPL_TOKEN_LIFECYCLE_DESTINATION"),
|
||||||
required_pubkey_env("KB_DEVNET_SPL_TOKEN_LIFECYCLE_DELEGATE"),
|
required_pubkey_env("KS_DEVNET_SPL_TOKEN_LIFECYCLE_DELEGATE"),
|
||||||
required_pubkey_env("KB_DEVNET_SPL_TOKEN_LIFECYCLE_AUTHORITY"),
|
required_pubkey_env("KS_DEVNET_SPL_TOKEN_LIFECYCLE_AUTHORITY"),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let mut request = crate::DevnetSplTokenLifecycleRequest::new(
|
let mut request = crate::DevnetSplTokenLifecycleRequest::new(
|
||||||
@@ -1618,33 +1618,33 @@ mod tests {
|
|||||||
delegate,
|
delegate,
|
||||||
authority,
|
authority,
|
||||||
);
|
);
|
||||||
request.decimals = optional_u8_env("KB_DEVNET_SPL_TOKEN_LIFECYCLE_DECIMALS", 9);
|
request.decimals = optional_u8_env("KS_DEVNET_SPL_TOKEN_LIFECYCLE_DECIMALS", 9);
|
||||||
request.mint_amount = ks_lib::ExSplClassicTokenAmount(optional_string_env(
|
request.mint_amount = ks_lib::ExSplClassicTokenAmount(optional_string_env(
|
||||||
"KB_DEVNET_SPL_TOKEN_LIFECYCLE_MINT_AMOUNT",
|
"KS_DEVNET_SPL_TOKEN_LIFECYCLE_MINT_AMOUNT",
|
||||||
"10",
|
"10",
|
||||||
));
|
));
|
||||||
request.transfer_amount = ks_lib::ExSplClassicTokenAmount(optional_string_env(
|
request.transfer_amount = ks_lib::ExSplClassicTokenAmount(optional_string_env(
|
||||||
"KB_DEVNET_SPL_TOKEN_LIFECYCLE_TRANSFER_AMOUNT",
|
"KS_DEVNET_SPL_TOKEN_LIFECYCLE_TRANSFER_AMOUNT",
|
||||||
"4",
|
"4",
|
||||||
));
|
));
|
||||||
request.approve_amount = ks_lib::ExSplClassicTokenAmount(optional_string_env(
|
request.approve_amount = ks_lib::ExSplClassicTokenAmount(optional_string_env(
|
||||||
"KB_DEVNET_SPL_TOKEN_LIFECYCLE_APPROVE_AMOUNT",
|
"KS_DEVNET_SPL_TOKEN_LIFECYCLE_APPROVE_AMOUNT",
|
||||||
"2",
|
"2",
|
||||||
));
|
));
|
||||||
request.submit = true;
|
request.submit = true;
|
||||||
request.operator_confirmed = true;
|
request.operator_confirmed = true;
|
||||||
request.post_validation_max_retries = 20;
|
request.post_validation_max_retries = 20;
|
||||||
request.first_step_index =
|
request.first_step_index =
|
||||||
optional_u8_env("KB_DEVNET_SPL_TOKEN_LIFECYCLE_FIRST_STEP_INDEX", 0);
|
optional_u8_env("KS_DEVNET_SPL_TOKEN_LIFECYCLE_FIRST_STEP_INDEX", 0);
|
||||||
request.resume_predecessor_signature = if request.first_step_index > 0 {
|
request.resume_predecessor_signature = if request.first_step_index > 0 {
|
||||||
std::option::Option::Some(ks_lib::MdSignature(required_string_env(
|
std::option::Option::Some(ks_lib::MdSignature(required_string_env(
|
||||||
"KB_DEVNET_SPL_TOKEN_LIFECYCLE_RESUME_PREDECESSOR_SIGNATURE",
|
"KS_DEVNET_SPL_TOKEN_LIFECYCLE_RESUME_PREDECESSOR_SIGNATURE",
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
std::option::Option::None
|
std::option::Option::None
|
||||||
};
|
};
|
||||||
request.inter_step_delay_ms =
|
request.inter_step_delay_ms =
|
||||||
optional_u64_env("KB_DEVNET_SPL_TOKEN_LIFECYCLE_INTER_STEP_DELAY_MS", 2_000);
|
optional_u64_env("KS_DEVNET_SPL_TOKEN_LIFECYCLE_INTER_STEP_DELAY_MS", 2_000);
|
||||||
let decoders: std::vec::Vec<std::sync::Arc<dyn ks_lib::DcApiInstructionDecoder>> =
|
let decoders: std::vec::Vec<std::sync::Arc<dyn ks_lib::DcApiInstructionDecoder>> =
|
||||||
std::vec![std::sync::Arc::new(ks_lib::DcSplTokenDecoder)];
|
std::vec![std::sync::Arc::new(ks_lib::DcSplTokenDecoder)];
|
||||||
let materializers: std::vec::Vec<std::sync::Arc<dyn ks_lib::MtApiEventMaterializer>> =
|
let materializers: std::vec::Vec<std::sync::Arc<dyn ks_lib::MtApiEventMaterializer>> =
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/spl/token_2022/devnet_scenarios.rs
|
// file: ks-pipeline-demo-scenarios/src/spl/token_2022/devnet_scenarios.rs
|
||||||
// version: 9
|
// version: 10
|
||||||
|
|
||||||
//! Stable Devnet validation scenarios required to close milestone 0.4.6.
|
//! Stable Devnet validation scenarios required to close milestone 0.4.6.
|
||||||
|
|
||||||
@@ -53,17 +53,17 @@ pub struct DevnetSplValidationScenario {
|
|||||||
/// Returns the complete ordered Devnet scenario inventory for milestone 0.4.6.
|
/// Returns the complete ordered Devnet scenario inventory for milestone 0.4.6.
|
||||||
pub fn devnet_spl_validation_scenarios() -> std::vec::Vec<crate::DevnetSplValidationScenario> {
|
pub fn devnet_spl_validation_scenarios() -> std::vec::Vec<crate::DevnetSplValidationScenario> {
|
||||||
return vec![
|
return vec![
|
||||||
public_scenario("token_2022_mint_to_checked", "Token-2022 MintToChecked", ks_lib::EX_SPL_TOKEN_2022_MINT_TO_CHECKED_OPERATION, &["TOKEN_2022_MINT", "TOKEN_2022_SOURCE", "TOKEN_2022_AUTHORITY", "TOKEN_2022_DECIMALS", "TOKEN_2022_MINT_AMOUNT_RAW"]),
|
public_scenario("token_2022_mint_to_checked", "Token-2022 MintToChecked", ks_lib::EX_SPL_TOKEN_2022_MINT_TO_CHECKED_OPERATION, &["KS_PUBLIC_DEVNET_TOKEN_2022_MINT", "KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE", "KS_PUBLIC_DEVNET_TOKEN_2022_AUTHORITY", "KS_PUBLIC_DEVNET_TOKEN_2022_DECIMALS", "KS_PUBLIC_DEVNET_TOKEN_2022_MINT_AMOUNT_RAW"]),
|
||||||
public_scenario("token_2022_transfer_checked", "Token-2022 TransferChecked", ks_lib::EX_SPL_TOKEN_2022_TRANSFER_CHECKED_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_MINT", "TOKEN_2022_DESTINATION", "TOKEN_2022_AUTHORITY", "TOKEN_2022_DECIMALS", "TOKEN_2022_TRANSFER_AMOUNT_RAW"]),
|
public_scenario("token_2022_transfer_checked", "Token-2022 TransferChecked", ks_lib::EX_SPL_TOKEN_2022_TRANSFER_CHECKED_OPERATION, &["KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE", "KS_PUBLIC_DEVNET_TOKEN_2022_MINT", "KS_PUBLIC_DEVNET_TOKEN_2022_DESTINATION", "KS_PUBLIC_DEVNET_TOKEN_2022_AUTHORITY", "KS_PUBLIC_DEVNET_TOKEN_2022_DECIMALS", "KS_PUBLIC_DEVNET_TOKEN_2022_TRANSFER_AMOUNT_RAW"]),
|
||||||
public_scenario("token_2022_approve_checked", "Token-2022 ApproveChecked", ks_lib::EX_SPL_TOKEN_2022_APPROVE_CHECKED_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_MINT", "TOKEN_2022_DELEGATE", "TOKEN_2022_AUTHORITY", "TOKEN_2022_DECIMALS", "TOKEN_2022_APPROVE_AMOUNT_RAW"]),
|
public_scenario("token_2022_approve_checked", "Token-2022 ApproveChecked", ks_lib::EX_SPL_TOKEN_2022_APPROVE_CHECKED_OPERATION, &["KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE", "KS_PUBLIC_DEVNET_TOKEN_2022_MINT", "KS_PUBLIC_DEVNET_TOKEN_2022_DELEGATE", "KS_PUBLIC_DEVNET_TOKEN_2022_AUTHORITY", "KS_PUBLIC_DEVNET_TOKEN_2022_DECIMALS", "KS_PUBLIC_DEVNET_TOKEN_2022_APPROVE_AMOUNT_RAW"]),
|
||||||
public_scenario("token_2022_revoke", "Token-2022 Revoke", ks_lib::EX_SPL_TOKEN_2022_REVOKE_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_AUTHORITY"]),
|
public_scenario("token_2022_revoke", "Token-2022 Revoke", ks_lib::EX_SPL_TOKEN_2022_REVOKE_OPERATION, &["KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE", "KS_PUBLIC_DEVNET_TOKEN_2022_AUTHORITY"]),
|
||||||
public_scenario("token_2022_burn_checked", "Token-2022 BurnChecked", ks_lib::EX_SPL_TOKEN_2022_BURN_CHECKED_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_MINT", "TOKEN_2022_AUTHORITY", "TOKEN_2022_DECIMALS", "TOKEN_2022_BURN_AMOUNT_RAW"]),
|
public_scenario("token_2022_burn_checked", "Token-2022 BurnChecked", ks_lib::EX_SPL_TOKEN_2022_BURN_CHECKED_OPERATION, &["KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE", "KS_PUBLIC_DEVNET_TOKEN_2022_MINT", "KS_PUBLIC_DEVNET_TOKEN_2022_AUTHORITY", "KS_PUBLIC_DEVNET_TOKEN_2022_DECIMALS", "KS_PUBLIC_DEVNET_TOKEN_2022_BURN_AMOUNT_RAW"]),
|
||||||
public_scenario("token_2022_freeze_account", "Token-2022 FreezeAccount", ks_lib::EX_SPL_TOKEN_2022_FREEZE_ACCOUNT_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_MINT", "TOKEN_2022_FREEZE_AUTHORITY"]),
|
public_scenario("token_2022_freeze_account", "Token-2022 FreezeAccount", ks_lib::EX_SPL_TOKEN_2022_FREEZE_ACCOUNT_OPERATION, &["KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE", "KS_PUBLIC_DEVNET_TOKEN_2022_MINT", "KS_PUBLIC_DEVNET_TOKEN_2022_FREEZE_AUTHORITY"]),
|
||||||
public_scenario("token_2022_thaw_account", "Token-2022 ThawAccount", ks_lib::EX_SPL_TOKEN_2022_THAW_ACCOUNT_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_MINT", "TOKEN_2022_FREEZE_AUTHORITY"]),
|
public_scenario("token_2022_thaw_account", "Token-2022 ThawAccount", ks_lib::EX_SPL_TOKEN_2022_THAW_ACCOUNT_OPERATION, &["KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE", "KS_PUBLIC_DEVNET_TOKEN_2022_MINT", "KS_PUBLIC_DEVNET_TOKEN_2022_FREEZE_AUTHORITY"]),
|
||||||
public_scenario("token_2022_close_destination", "Token-2022 CloseAccount destination", ks_lib::EX_SPL_TOKEN_2022_CLOSE_ACCOUNT_OPERATION, &["TOKEN_2022_DESTINATION", "KB_DEVNET_WALLET_ADDRESS", "TOKEN_2022_AUTHORITY"]),
|
public_scenario("token_2022_close_destination", "Token-2022 CloseAccount destination", ks_lib::EX_SPL_TOKEN_2022_CLOSE_ACCOUNT_OPERATION, &["KS_PUBLIC_DEVNET_TOKEN_2022_DESTINATION", "KS_PUBLIC_DEVNET_WALLET_ADDRESS", "KS_PUBLIC_DEVNET_TOKEN_2022_AUTHORITY"]),
|
||||||
registry_scenario("elgamal_registry_create", "ElGamal Registry CreateRegistry", "spl.elgamal_registry.create_registry", &["ELGAMAL_REGISTRY_ADDRESS", "ELGAMAL_PUBKEY_BASE64", "PUBKEY_VALIDITY_PROOF_CONTEXT"]),
|
registry_scenario("elgamal_registry_create", "ElGamal Registry CreateRegistry", "spl.elgamal_registry.create_registry", &["KS_PUBLIC_DEVNET_ELGAMAL_REGISTRY_ADDRESS", "KS_PUBLIC_DEVNET_ELGAMAL_PUBKEY_BASE64", "KS_PUBLIC_DEVNET_PUBKEY_VALIDITY_PROOF_CONTEXT"]),
|
||||||
registry_scenario("elgamal_registry_update", "ElGamal Registry UpdateRegistry", "spl.elgamal_registry.update_registry", &["ELGAMAL_REGISTRY_ADDRESS", "ELGAMAL_PUBKEY_BASE64", "PUBKEY_VALIDITY_PROOF_CONTEXT"]),
|
registry_scenario("elgamal_registry_update", "ElGamal Registry UpdateRegistry", "spl.elgamal_registry.update_registry", &["KS_PUBLIC_DEVNET_ELGAMAL_REGISTRY_ADDRESS", "KS_PUBLIC_DEVNET_ELGAMAL_PUBKEY_BASE64", "KS_PUBLIC_DEVNET_PUBKEY_VALIDITY_PROOF_CONTEXT"]),
|
||||||
confidential_scenario("token_2022_configure_confidential_account", "Token-2022 ConfigureAccountWithRegistry", ks_lib::EX_SPL_TOKEN_2022_CONFIGURE_CONFIDENTIAL_TRANSFER_ACCOUNT_WITH_REGISTRY_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_MINT", "ELGAMAL_REGISTRY_ADDRESS", "PUBKEY_VALIDITY_PROOF_CONTEXT"]),
|
confidential_scenario("token_2022_configure_confidential_account", "Token-2022 ConfigureAccountWithRegistry", ks_lib::EX_SPL_TOKEN_2022_CONFIGURE_CONFIDENTIAL_TRANSFER_ACCOUNT_WITH_REGISTRY_OPERATION, &["KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE", "KS_PUBLIC_DEVNET_TOKEN_2022_MINT", "KS_PUBLIC_DEVNET_ELGAMAL_REGISTRY_ADDRESS", "KS_PUBLIC_DEVNET_PUBKEY_VALIDITY_PROOF_CONTEXT"]),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/spl/token_2022/fixture.rs
|
// file: ks-pipeline-demo-scenarios/src/spl/token_2022/fixture.rs
|
||||||
// version: 4
|
// version: 5
|
||||||
|
|
||||||
//! Idempotent Token-2022 public scenario fixture preparation.
|
//! Idempotent Token-2022 public scenario fixture preparation.
|
||||||
|
|
||||||
@@ -376,7 +376,7 @@ fn path_text(path: &std::path::Path) -> ks_core::Result<std::string::String> {
|
|||||||
|
|
||||||
fn render_fixture(summary: &crate::Token2022FixturePreparationSummary) -> std::string::String {
|
fn render_fixture(summary: &crate::Token2022FixturePreparationSummary) -> std::string::String {
|
||||||
return format!(
|
return format!(
|
||||||
"export TOKEN_2022_PROGRAM={}\nexport TOKEN_2022_MINT={}\nexport TOKEN_2022_SOURCE={}\nexport TOKEN_2022_DESTINATION={}\nexport TOKEN_2022_CLOSE_ACCOUNT={}\nexport TOKEN_2022_DELEGATE={}\nexport TOKEN_2022_AUTHORITY={}\nexport TOKEN_2022_FREEZE_AUTHORITY={}\nexport TOKEN_2022_DECIMALS={}\nexport TOKEN_2022_MINT_AMOUNT_RAW={}\nexport TOKEN_2022_TRANSFER_AMOUNT_RAW={}\nexport TOKEN_2022_APPROVE_AMOUNT_RAW={}\nexport TOKEN_2022_BURN_AMOUNT_RAW={}\nexport KB_DEVNET_WALLET_ADDRESS={}\n",
|
"export KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID={}\nexport KS_PUBLIC_DEVNET_TOKEN_2022_MINT={}\nexport KS_PUBLIC_DEVNET_TOKEN_2022_SOURCE={}\nexport KS_PUBLIC_DEVNET_TOKEN_2022_DESTINATION={}\nexport KS_PUBLIC_DEVNET_TOKEN_2022_CLOSE_ACCOUNT={}\nexport KS_PUBLIC_DEVNET_TOKEN_2022_DELEGATE={}\nexport KS_PUBLIC_DEVNET_TOKEN_2022_AUTHORITY={}\nexport KS_PUBLIC_DEVNET_TOKEN_2022_FREEZE_AUTHORITY={}\nexport KS_PUBLIC_DEVNET_TOKEN_2022_DECIMALS={}\nexport KS_PUBLIC_DEVNET_TOKEN_2022_MINT_AMOUNT_RAW={}\nexport KS_PUBLIC_DEVNET_TOKEN_2022_TRANSFER_AMOUNT_RAW={}\nexport KS_PUBLIC_DEVNET_TOKEN_2022_APPROVE_AMOUNT_RAW={}\nexport KS_PUBLIC_DEVNET_TOKEN_2022_BURN_AMOUNT_RAW={}\nexport KS_PUBLIC_DEVNET_WALLET_ADDRESS={}\n",
|
||||||
summary.program_id,
|
summary.program_id,
|
||||||
summary.mint,
|
summary.mint,
|
||||||
summary.source,
|
summary.source,
|
||||||
@@ -444,8 +444,8 @@ mod tests {
|
|||||||
assert!(fixture.lines().any(|line| return line.starts_with(format!("export {variable}=").as_str())), "missing {variable}");
|
assert!(fixture.lines().any(|line| return line.starts_with(format!("export {variable}=").as_str())), "missing {variable}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert!(fixture.contains("export TOKEN_2022_CLOSE_ACCOUNT=close\n"));
|
assert!(fixture.contains("export KS_PUBLIC_DEVNET_TOKEN_2022_CLOSE_ACCOUNT=close\n"));
|
||||||
assert!(fixture.contains("export KB_DEVNET_WALLET_ADDRESS=authority\n"));
|
assert!(fixture.contains("export KS_PUBLIC_DEVNET_WALLET_ADDRESS=authority\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline-demo-scenarios/src/spl/token_2022/metadata/campaign.rs
|
// file: ks-pipeline-demo-scenarios/src/spl/token_2022/metadata/campaign.rs
|
||||||
// version: 5
|
// version: 6
|
||||||
|
|
||||||
//! Ordered confirmed Devnet campaign for the five Token-2022 Token Metadata instructions.
|
//! Ordered confirmed Devnet campaign for the five Token-2022 Token Metadata instructions.
|
||||||
|
|
||||||
@@ -479,25 +479,25 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_token_2022_metadata_campaign_from_env() {
|
async fn optional_devnet_token_2022_metadata_campaign_from_env() {
|
||||||
if std::env::var("KB_DEVNET_TOKEN_2022_METADATA_CAMPAIGN_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_TOKEN_2022_METADATA_CAMPAIGN_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if std::env::var("KB_DEVNET_TOKEN_2022_METADATA_OPERATOR_CONFIRMED")
|
if std::env::var("KS_DEVNET_TOKEN_2022_METADATA_OPERATOR_CONFIRMED")
|
||||||
.ok()
|
.ok()
|
||||||
.as_deref()
|
.as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
panic!(
|
panic!(
|
||||||
"KB_DEVNET_TOKEN_2022_METADATA_OPERATOR_CONFIRMED=1 is required for the spending campaign"
|
"KS_DEVNET_TOKEN_2022_METADATA_OPERATOR_CONFIRMED=1 is required for the spending campaign"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
let workspace_root = match std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent() {
|
||||||
std::option::Option::Some(value) => value,
|
std::option::Option::Some(value) => value,
|
||||||
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
std::option::Option::None => panic!("workspace root cannot be resolved"),
|
||||||
};
|
};
|
||||||
let config_path = match std::env::var("KB_DEVNET_CONFIG_PATH") {
|
let config_path = match std::env::var("KS_DEVNET_CONFIG_PATH") {
|
||||||
std::result::Result::Ok(value) => {
|
std::result::Result::Ok(value) => {
|
||||||
let path = std::path::PathBuf::from(value);
|
let path = std::path::PathBuf::from(value);
|
||||||
if path.is_absolute() { path } else { workspace_root.join(path) }
|
if path.is_absolute() { path } else { workspace_root.join(path) }
|
||||||
@@ -509,11 +509,11 @@ mod tests {
|
|||||||
workspace_root,
|
workspace_root,
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet configuration loading failed: {error}"));
|
||||||
let profile_name = std::env::var("KB_DEVNET_PROFILE").ok();
|
let profile_name = std::env::var("KS_DEVNET_PROFILE").ok();
|
||||||
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
let mut profile = crate::resolve_demo_devnet_profile(&config, profile_name.as_deref())
|
||||||
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
.unwrap_or_else(|error| panic!("Devnet profile resolution failed: {error}"));
|
||||||
let database_url = std::env::var("KB_POSTGRES_TEST_URL")
|
let database_url = std::env::var("KS_SECRET_POSTGRES_TEST_URL")
|
||||||
.unwrap_or_else(|error| panic!("KB_POSTGRES_TEST_URL is required: {error}"));
|
.unwrap_or_else(|error| panic!("KS_SECRET_POSTGRES_TEST_URL is required: {error}"));
|
||||||
profile.database.backend = "postgres".to_string();
|
profile.database.backend = "postgres".to_string();
|
||||||
profile.database.postgres.url = database_url;
|
profile.database.postgres.url = database_url;
|
||||||
let pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
let pool = ks_onchain_transport::HttpEndpointPool::from_profile(&profile)
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
<!-- file: ks-pipeline/CHANGELOG.md -->
|
<!-- file: ks-pipeline/CHANGELOG.md -->
|
||||||
<!-- version: 32 -->
|
<!-- version: 33 -->
|
||||||
|
|
||||||
# CHANGELOG — ks-pipeline
|
# CHANGELOG — ks-pipeline
|
||||||
|
|
||||||
|
## `0.5.1-pre.004`
|
||||||
|
|
||||||
|
- migre les variables des tests Devnet SPL Token vers le namespace interne `KS_*` ;
|
||||||
|
- ne modifie aucune orchestration, opération, simulation ou postcondition.
|
||||||
|
|
||||||
## `0.5.1-pre.003`
|
## `0.5.1-pre.003`
|
||||||
|
|
||||||
- aligne les tests d'orchestration sur les nouvelles identités d'exécuteurs `ks-lib-executor.*` ;
|
- aligne les tests d'orchestration sur les nouvelles identités d'exécuteurs `ks-lib-executor.*` ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-pipeline/src/spl_token_stateful.rs
|
// file: ks-pipeline/src/spl_token_stateful.rs
|
||||||
// version: 3
|
// version: 4
|
||||||
|
|
||||||
//! Stateful Localnet and Devnet readiness checks for classic SPL Token operations.
|
//! Stateful Localnet and Devnet readiness checks for classic SPL Token operations.
|
||||||
|
|
||||||
@@ -1614,45 +1614,45 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_devnet_checked_transfer_readiness_from_env() {
|
async fn optional_devnet_checked_transfer_readiness_from_env() {
|
||||||
if std::env::var("KB_DEVNET_SPL_TOKEN_PREFLIGHT_TEST").ok().as_deref()
|
if std::env::var("KS_DEVNET_SPL_TOKEN_PREFLIGHT_TEST").ok().as_deref()
|
||||||
!= std::option::Option::Some("1")
|
!= std::option::Option::Some("1")
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let source = match std::env::var("KB_DEVNET_SPL_TOKEN_SOURCE") {
|
let source = match std::env::var("KS_DEVNET_SPL_TOKEN_SOURCE") {
|
||||||
std::result::Result::Ok(value) => ks_lib::MdPubkey(value),
|
std::result::Result::Ok(value) => ks_lib::MdPubkey(value),
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
panic!("KB_DEVNET_SPL_TOKEN_SOURCE is required: {error}");
|
panic!("KS_DEVNET_SPL_TOKEN_SOURCE is required: {error}");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let mint = match std::env::var("KB_DEVNET_SPL_TOKEN_MINT") {
|
let mint = match std::env::var("KS_DEVNET_SPL_TOKEN_MINT") {
|
||||||
std::result::Result::Ok(value) => ks_lib::MdPubkey(value),
|
std::result::Result::Ok(value) => ks_lib::MdPubkey(value),
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
panic!("KB_DEVNET_SPL_TOKEN_MINT is required: {error}");
|
panic!("KS_DEVNET_SPL_TOKEN_MINT is required: {error}");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let destination = match std::env::var("KB_DEVNET_SPL_TOKEN_DESTINATION") {
|
let destination = match std::env::var("KS_DEVNET_SPL_TOKEN_DESTINATION") {
|
||||||
std::result::Result::Ok(value) => ks_lib::MdPubkey(value),
|
std::result::Result::Ok(value) => ks_lib::MdPubkey(value),
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
panic!("KB_DEVNET_SPL_TOKEN_DESTINATION is required: {error}");
|
panic!("KS_DEVNET_SPL_TOKEN_DESTINATION is required: {error}");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let authority = match std::env::var("KB_DEVNET_SPL_TOKEN_AUTHORITY") {
|
let authority = match std::env::var("KS_DEVNET_SPL_TOKEN_AUTHORITY") {
|
||||||
std::result::Result::Ok(value) => ks_lib::MdPubkey(value),
|
std::result::Result::Ok(value) => ks_lib::MdPubkey(value),
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
panic!("KB_DEVNET_SPL_TOKEN_AUTHORITY is required: {error}");
|
panic!("KS_DEVNET_SPL_TOKEN_AUTHORITY is required: {error}");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let decimals = match std::env::var("KB_DEVNET_SPL_TOKEN_DECIMALS") {
|
let decimals = match std::env::var("KS_DEVNET_SPL_TOKEN_DECIMALS") {
|
||||||
std::result::Result::Ok(value) => match value.parse::<u8>() {
|
std::result::Result::Ok(value) => match value.parse::<u8>() {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
panic!("KB_DEVNET_SPL_TOKEN_DECIMALS must be a u8: {error}");
|
panic!("KS_DEVNET_SPL_TOKEN_DECIMALS must be a u8: {error}");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
std::result::Result::Err(_) => 9,
|
std::result::Result::Err(_) => 9,
|
||||||
};
|
};
|
||||||
let amount = match std::env::var("KB_DEVNET_SPL_TOKEN_AMOUNT") {
|
let amount = match std::env::var("KS_DEVNET_SPL_TOKEN_AMOUNT") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(_) => "1".to_string(),
|
std::result::Result::Err(_) => "1".to_string(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
<!-- file: ks-store/CHANGELOG.md -->
|
<!-- file: ks-store/CHANGELOG.md -->
|
||||||
<!-- version: 14 -->
|
<!-- version: 15 -->
|
||||||
|
|
||||||
# CHANGELOG — ks-store
|
# CHANGELOG — ks-store
|
||||||
|
|
||||||
|
## `0.5.1-pre.004`
|
||||||
|
|
||||||
|
- migre la variable des tests PostgreSQL optionnels vers `KS_SECRET_POSTGRES_TEST_URL` ;
|
||||||
|
- renomme le helper SQL de rollback réservé aux tests de `kb_test_reject_decode_ledger` vers `ks_test_reject_decode_ledger` ;
|
||||||
|
- ne modifie aucune migration, table, requête SQL ou identité persistée.
|
||||||
|
|
||||||
## `0.5.1-pre.003`
|
## `0.5.1-pre.003`
|
||||||
|
|
||||||
- aligne le contrat de test de persistance/replay sur l'identité de décodeur `ks-lib-decoder.*` ;
|
- aligne le contrat de test de persistance/replay sur l'identité de décodeur `ks-lib-decoder.*` ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-store/src/postgres/query/core_extraction_queries.rs
|
// file: ks-store/src/postgres/query/core_extraction_queries.rs
|
||||||
// version: 3
|
// version: 4
|
||||||
|
|
||||||
//! PostgreSQL queries for atomic canonical transaction to core extraction.
|
//! PostgreSQL queries for atomic canonical transaction to core extraction.
|
||||||
|
|
||||||
@@ -779,7 +779,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_postgres_core_extraction_rolls_back_partial_graph_from_env() {
|
async fn optional_postgres_core_extraction_rolls_back_partial_graph_from_env() {
|
||||||
let database_url = match std::env::var("KB_POSTGRES_TEST_URL") {
|
let database_url = match std::env::var("KS_SECRET_POSTGRES_TEST_URL") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(_error) => return,
|
std::result::Result::Err(_error) => return,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-store/src/postgres/query/core_queries.rs
|
// file: ks-store/src/postgres/query/core_queries.rs
|
||||||
// version: 3
|
// version: 4
|
||||||
|
|
||||||
//! PostgreSQL queries for normalized Solana core storage.
|
//! PostgreSQL queries for normalized Solana core storage.
|
||||||
|
|
||||||
@@ -986,7 +986,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_postgres_core_store_roundtrip_from_env() {
|
async fn optional_postgres_core_store_roundtrip_from_env() {
|
||||||
let database_url = match std::env::var("KB_POSTGRES_TEST_URL") {
|
let database_url = match std::env::var("KS_SECRET_POSTGRES_TEST_URL") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(_error) => return,
|
std::result::Result::Err(_error) => return,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-store/src/postgres/query/decode_pipeline_queries.rs
|
// file: ks-store/src/postgres/query/decode_pipeline_queries.rs
|
||||||
// version: 6
|
// version: 7
|
||||||
|
|
||||||
//! PostgreSQL queries for contextual decode, coverage and materialization persistence.
|
//! PostgreSQL queries for contextual decode, coverage and materialization persistence.
|
||||||
|
|
||||||
@@ -1029,7 +1029,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn test_pool_from_env() -> std::option::Option<sqlx::PgPool> {
|
async fn test_pool_from_env() -> std::option::Option<sqlx::PgPool> {
|
||||||
let url = match std::env::var("KB_POSTGRES_TEST_URL") {
|
let url = match std::env::var("KS_SECRET_POSTGRES_TEST_URL") {
|
||||||
std::result::Result::Ok(value) if !value.trim().is_empty() => value,
|
std::result::Result::Ok(value) if !value.trim().is_empty() => value,
|
||||||
_ => return std::option::Option::None,
|
_ => return std::option::Option::None,
|
||||||
};
|
};
|
||||||
@@ -1207,7 +1207,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn decoded_events_and_ledger_roll_back_together() {
|
async fn decoded_events_and_ledger_roll_back_together() {
|
||||||
let url = match std::env::var("KB_POSTGRES_TEST_URL") {
|
let url = match std::env::var("KS_SECRET_POSTGRES_TEST_URL") {
|
||||||
std::result::Result::Ok(value) if !value.trim().is_empty() => value,
|
std::result::Result::Ok(value) if !value.trim().is_empty() => value,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
@@ -1236,17 +1236,17 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
execute_sql(
|
execute_sql(
|
||||||
&pool,
|
&pool,
|
||||||
"CREATE OR REPLACE FUNCTION kb_test_reject_decode_ledger() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN IF NEW.processor_name = 'decode_atomic_rollback_test' THEN RAISE EXCEPTION 'forced decode ledger failure'; END IF; RETURN NEW; END; $$",
|
"CREATE OR REPLACE FUNCTION ks_test_reject_decode_ledger() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN IF NEW.processor_name = 'decode_atomic_rollback_test' THEN RAISE EXCEPTION 'forced decode ledger failure'; END IF; RETURN NEW; END; $$",
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
execute_sql(
|
execute_sql(
|
||||||
&pool,
|
&pool,
|
||||||
"DROP TRIGGER IF EXISTS kb_test_reject_decode_ledger_trigger ON kb_sol_ops_processing_ledger",
|
"DROP TRIGGER IF EXISTS ks_test_reject_decode_ledger_trigger ON kb_sol_ops_processing_ledger",
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
execute_sql(
|
execute_sql(
|
||||||
&pool,
|
&pool,
|
||||||
"CREATE TRIGGER kb_test_reject_decode_ledger_trigger BEFORE INSERT OR UPDATE ON kb_sol_ops_processing_ledger FOR EACH ROW EXECUTE FUNCTION kb_test_reject_decode_ledger()",
|
"CREATE TRIGGER ks_test_reject_decode_ledger_trigger BEFORE INSERT OR UPDATE ON kb_sol_ops_processing_ledger FOR EACH ROW EXECUTE FUNCTION ks_test_reject_decode_ledger()",
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let identity_result = crate::ProcessingLedgerIdentity::new(
|
let identity_result = crate::ProcessingLedgerIdentity::new(
|
||||||
@@ -1332,9 +1332,9 @@ mod tests {
|
|||||||
assert_eq!(ledger_count, 0);
|
assert_eq!(ledger_count, 0);
|
||||||
execute_sql(
|
execute_sql(
|
||||||
&pool,
|
&pool,
|
||||||
"DROP TRIGGER IF EXISTS kb_test_reject_decode_ledger_trigger ON kb_sol_ops_processing_ledger",
|
"DROP TRIGGER IF EXISTS ks_test_reject_decode_ledger_trigger ON kb_sol_ops_processing_ledger",
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
execute_sql(&pool, "DROP FUNCTION IF EXISTS kb_test_reject_decode_ledger()").await;
|
execute_sql(&pool, "DROP FUNCTION IF EXISTS ks_test_reject_decode_ledger()").await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-store/src/postgres/query/raw_queries.rs
|
// file: ks-store/src/postgres/query/raw_queries.rs
|
||||||
// version: 3
|
// version: 4
|
||||||
|
|
||||||
//! PostgreSQL canonical transaction and acquisition observation SQL queries.
|
//! PostgreSQL canonical transaction and acquisition observation SQL queries.
|
||||||
|
|
||||||
@@ -374,7 +374,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_postgres_canonical_store_roundtrip_from_env() {
|
async fn optional_postgres_canonical_store_roundtrip_from_env() {
|
||||||
let database_url = match std::env::var("KB_POSTGRES_TEST_URL") {
|
let database_url = match std::env::var("KS_SECRET_POSTGRES_TEST_URL") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(_error) => return,
|
std::result::Result::Err(_error) => return,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-store/src/postgres/query/replay_candidate_queries.rs
|
// file: ks-store/src/postgres/query/replay_candidate_queries.rs
|
||||||
// version: 3
|
// version: 4
|
||||||
|
|
||||||
//! Read-only PostgreSQL queries for replay candidate discovery.
|
//! Read-only PostgreSQL queries for replay candidate discovery.
|
||||||
|
|
||||||
@@ -396,7 +396,7 @@ fn optional_sql_bigint(
|
|||||||
mod tests {
|
mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_postgres_replay_candidate_queries_from_env() {
|
async fn optional_postgres_replay_candidate_queries_from_env() {
|
||||||
let database_url = match std::env::var("KB_POSTGRES_TEST_URL") {
|
let database_url = match std::env::var("KS_SECRET_POSTGRES_TEST_URL") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(_error) => return,
|
std::result::Result::Err(_error) => return,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-store/src/postgres/store.rs
|
// file: ks-store/src/postgres/store.rs
|
||||||
// version: 3
|
// version: 4
|
||||||
|
|
||||||
//! Store implementation scaffold for the `ks-store` crate.
|
//! Store implementation scaffold for the `ks-store` crate.
|
||||||
|
|
||||||
@@ -467,7 +467,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn optional_postgres_healthcheck_from_env() {
|
async fn optional_postgres_healthcheck_from_env() {
|
||||||
let database_url = match std::env::var("KB_POSTGRES_TEST_URL") {
|
let database_url = match std::env::var("KS_SECRET_POSTGRES_TEST_URL") {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(_error) => return,
|
std::result::Result::Err(_error) => return,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: prompts/030_v0_5_1_khadhroony_solana_namespace_and_config.md -->
|
<!-- file: prompts/030_v0_5_1_khadhroony_solana_namespace_and_config.md -->
|
||||||
<!-- version: 2 -->
|
<!-- version: 3 -->
|
||||||
|
|
||||||
# Khadhroony Bot3 — `0.5.1` — migration Khadhroony Solana et configuration sûre
|
# Khadhroony Bot3 — `0.5.1` — migration Khadhroony Solana et configuration sûre
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ Reprendre `khadhroony-bot3` après la clôture validée de `0.5.0` et exécuter
|
|||||||
`0.5.1` doit accomplir deux objectifs liés :
|
`0.5.1` doit accomplir deux objectifs liés :
|
||||||
|
|
||||||
1. séparer explicitement le domaine des bibliothèques Solana généralistes du domaine applicatif Khadhroony Bot en migrant les bibliothèques vers les namespaces `ks-*` / `ks_*` ;
|
1. séparer explicitement le domaine des bibliothèques Solana généralistes du domaine applicatif Khadhroony Bot en migrant les bibliothèques vers les namespaces `ks-*` / `ks_*` ;
|
||||||
2. restructurer la configuration sur cette nouvelle fondation, avec namespace d'environnement `KS_*`, séparation du logging et politique stricte de non-divulgation des secrets.
|
2. restructurer la configuration sur cette nouvelle fondation, avec `KS_*` pour les contrats Solana, `KB_*` réservé aux contrats Bot, séparation du logging et politique stricte de non-divulgation des secrets.
|
||||||
|
|
||||||
Cette version est une migration de fondation. Elle ne doit pas ouvrir de nouveau programme Anchor/DEX et ne doit pas absorber prématurément les chantiers `ks-wallet`, `ks-store` ou de complétude des scénarios réservés respectivement à `0.5.2`, `0.5.3` et `0.5.4`.
|
Cette version est une migration de fondation. Elle ne doit pas ouvrir de nouveau programme Anchor/DEX et ne doit pas absorber prématurément les chantiers `ks-wallet`, `ks-store` ou de complétude des scénarios réservés respectivement à `0.5.2`, `0.5.3` et `0.5.4`.
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ La release `0.5.0` est une version de cadrage sans restructuration runtime majeu
|
|||||||
- la séparation de domaine entre `khadhroony-solana` et `khadhroony-bot` ;
|
- la séparation de domaine entre `khadhroony-solana` et `khadhroony-bot` ;
|
||||||
- l'inventaire des frontières de configuration, logging, wallet, store, scénarios et desktop ;
|
- l'inventaire des frontières de configuration, logging, wallet, store, scénarios et desktop ;
|
||||||
- la cible de renommage des dix crates Solana généralistes ;
|
- la cible de renommage des dix crates Solana généralistes ;
|
||||||
- la convention d'environnement `KS_*` ;
|
- la convention d'environnement par ownership : `KS_*` pour Khadhroony Solana et `KB_*` pour les futurs contrats spécifiques au Bot ;
|
||||||
- le split obligatoire de la configuration généraliste et de la configuration logging ;
|
- le split obligatoire de la configuration généraliste et de la configuration logging ;
|
||||||
- la nécessité de séparer configuration source, runtime résolue et surfaces publiques/diagnostiques ;
|
- la nécessité de séparer configuration source, runtime résolue et surfaces publiques/diagnostiques ;
|
||||||
- la migration future des identités techniques `kb-lib.*` vers le domaine `ks-lib-*` ;
|
- la migration future des identités techniques `kb-lib.*` vers le domaine `ks-lib-*` ;
|
||||||
@@ -76,8 +76,8 @@ Elle doit produire au minimum :
|
|||||||
- la table exhaustive des dix crates et identifiants Rust à migrer ;
|
- la table exhaustive des dix crates et identifiants Rust à migrer ;
|
||||||
- la table des dépendances workspace et ordre de renommage ;
|
- la table des dépendances workspace et ordre de renommage ;
|
||||||
- l'inventaire des noms de packages, bins, libs, imports, exports, tests externes, scripts et documentation concernés ;
|
- l'inventaire des noms de packages, bins, libs, imports, exports, tests externes, scripts et documentation concernés ;
|
||||||
- l'inventaire exhaustif des variables d'environnement actuellement utilisées et leur nouveau nom `KS_*` ;
|
- l'inventaire exhaustif des variables d'environnement actuellement utilisées, leur propriétaire `KS` ou `KB` et leur nom canonique ;
|
||||||
- la classification de chaque variable en `KS_SECRET_*`, `KS_PUBLIC_*` ou `KS_*` interne ;
|
- la classification de chaque variable en `*_SECRET_*`, `*_PUBLIC_*` ou interne dans le namespace de son propriétaire ;
|
||||||
- l'inventaire des identités runtime/persistées et targets techniques à migrer ;
|
- l'inventaire des identités runtime/persistées et targets techniques à migrer ;
|
||||||
- l'inventaire des payloads Tauri/TS-RS pouvant actuellement transporter de la configuration résolue ;
|
- l'inventaire des payloads Tauri/TS-RS pouvant actuellement transporter de la configuration résolue ;
|
||||||
- l'inventaire des structures dupliquées entre configuration et logging ;
|
- l'inventaire des structures dupliquées entre configuration et logging ;
|
||||||
@@ -172,45 +172,22 @@ Cependant, le renommage physique des tables et la normalisation des migrations a
|
|||||||
|
|
||||||
## Namespace obligatoire des variables d'environnement
|
## Namespace obligatoire des variables d'environnement
|
||||||
|
|
||||||
Après migration, toute variable d'environnement appartenant au workspace doit commencer par `KS_`.
|
Le namespace suit le propriétaire fonctionnel du contrat :
|
||||||
|
|
||||||
La convention retenue est :
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
KS_SECRET_* secret absolu
|
Khadhroony Solana / ks-* : KS_SECRET_* / KS_PUBLIC_* / KS_*
|
||||||
KS_PUBLIC_* valeur explicitement candidate à une surface publique
|
Khadhroony Bot / kb-* : KB_SECRET_* / KB_PUBLIC_* / KB_*
|
||||||
KS_* valeur interne/diagnostique
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Une ancienne variable `KB_*` ou une variable projet sans préfixe `KS_` ne doit pas subsister dans le code, les exemples, tests ou documentation après fermeture de la migration.
|
Une variable de scénario ou de configuration Solana reste `KS_*` même si `kb-app-demo-desktop` la consomme. `KB_*` est réservé aux besoins réellement propres au desktop ou aux futures crates du Bot. Les variables standard de l'OS, de Cargo ou d'outils tiers ne sont pas renommées artificiellement.
|
||||||
|
|
||||||
Les variables du système d'exploitation ou de dépendances tierces ne sont pas renommées artificiellement si elles ne constituent pas un contrat de configuration Khadhroony.
|
Les classes ont la même sémantique dans les deux namespaces :
|
||||||
|
|
||||||
### `KS_SECRET_*`
|
- `*_SECRET_*` : secret absolu, jamais exposé ni loggé ;
|
||||||
|
- `*_PUBLIC_*` : candidate explicite à une surface publique, sans autorisation automatique d'exposition ;
|
||||||
|
- autres `KS_*` / `KB_*` : internes, absentes des payloads normaux.
|
||||||
|
|
||||||
Une valeur issue de `KS_SECRET_*` :
|
La migration des noms et la fermeture des alias legacy appartiennent à `pre.004`. La propagation de sensibilité dans les valeurs composées, le camouflage et les DTO publics sûrs sont réalisés après le split config/logging.
|
||||||
|
|
||||||
- peut être utilisée côté backend lorsque nécessaire ;
|
|
||||||
- ne doit jamais apparaître dans les logs ;
|
|
||||||
- ne doit jamais apparaître dans une erreur publique ;
|
|
||||||
- ne doit jamais être sérialisée vers Tauri ;
|
|
||||||
- ne doit jamais être exposée dans un diagnostic, même debug ;
|
|
||||||
- ne doit jamais être exportée par TS-RS comme valeur résolue ;
|
|
||||||
- doit rester secrète lorsqu'elle est incorporée dans une URL, DSN ou autre valeur composée.
|
|
||||||
|
|
||||||
Un diagnostic peut indiquer qu'un secret est configuré ou absent sans exposer sa valeur.
|
|
||||||
|
|
||||||
### `KS_PUBLIC_*`
|
|
||||||
|
|
||||||
Le préfixe `KS_PUBLIC_*` classe la variable comme publiable, mais ne constitue pas une autorisation automatique de parcourir l'environnement et de l'envoyer au frontend.
|
|
||||||
|
|
||||||
L'exposition doit être explicitement définie par un DTO ou une API publique.
|
|
||||||
|
|
||||||
### autres `KS_*`
|
|
||||||
|
|
||||||
Les autres variables `KS_*` sont internes. Elles ne sont pas exposées par les payloads normaux. Elles peuvent apparaître dans un diagnostic explicitement demandé lorsque leur sémantique n'est pas sensible.
|
|
||||||
|
|
||||||
Le simple fait de compiler en mode debug ne doit pas automatiquement exposer toutes les valeurs internes.
|
|
||||||
|
|
||||||
## Split obligatoire de la configuration
|
## Split obligatoire de la configuration
|
||||||
|
|
||||||
@@ -248,7 +225,7 @@ La restructuration doit empêcher qu'une configuration résolue complète puisse
|
|||||||
|
|
||||||
Distinguer au minimum :
|
Distinguer au minimum :
|
||||||
|
|
||||||
1. représentation source : fichiers, placeholders et références `${KS_*}` ;
|
1. représentation source : fichiers, placeholders et références `${KS_*}` / `${KB_*}` ;
|
||||||
2. représentation runtime : valeurs validées et résolues nécessaires au backend ;
|
2. représentation runtime : valeurs validées et résolues nécessaires au backend ;
|
||||||
3. représentation publique/diagnostique : DTO explicitement construits pour l'UI, les diagnostics ou une API externe.
|
3. représentation publique/diagnostique : DTO explicitement construits pour l'UI, les diagnostics ou une API externe.
|
||||||
|
|
||||||
@@ -302,12 +279,12 @@ Les commandes Tauri restent des adaptateurs minces :
|
|||||||
|
|
||||||
Ajouter des tests prouvant notamment que :
|
Ajouter des tests prouvant notamment que :
|
||||||
|
|
||||||
- une sentinelle issue de `KS_SECRET_*` n'apparaît dans aucune sérialisation publique ;
|
- une sentinelle issue de `KS_SECRET_*` ou `KB_SECRET_*` n'apparaît dans aucune sérialisation publique ;
|
||||||
- elle n'apparaît pas dans les erreurs publiques ;
|
- elle n'apparaît pas dans les erreurs publiques ;
|
||||||
- elle n'apparaît pas dans les diagnostics debug ;
|
- elle n'apparaît pas dans les diagnostics debug ;
|
||||||
- une URL ou DSN composée avec un secret est entièrement traitée comme sensible ;
|
- une URL ou DSN composée avec un secret est entièrement traitée comme sensible ;
|
||||||
- `KS_PUBLIC_*` n'est exposé que par une surface explicitement autorisée ;
|
- `KS_PUBLIC_*` / `KB_PUBLIC_*` n'est exposé que par une surface explicitement autorisée ;
|
||||||
- une variable `KS_*` interne n'apparaît pas dans le payload normal ;
|
- une variable interne `KS_*` / `KB_*` n'apparaît pas dans le payload normal ;
|
||||||
- les anciens noms d'environnement sont absents après migration ;
|
- les anciens noms d'environnement sont absents après migration ;
|
||||||
- les schémas JSON général et logging valident leurs documents respectifs ;
|
- les schémas JSON général et logging valident leurs documents respectifs ;
|
||||||
- le choix d'un profil logging est indépendant du profil général ;
|
- le choix d'un profil logging est indépendant du profil général ;
|
||||||
@@ -336,29 +313,36 @@ Le détail doit être confirmé par `0.5.1-pre.001`, mais la trajectoire cible e
|
|||||||
- maintenir un workspace compilable et auditable ;
|
- maintenir un workspace compilable et auditable ;
|
||||||
- conserver `kb-app-demo-desktop`.
|
- conserver `kb-app-demo-desktop`.
|
||||||
|
|
||||||
### `0.5.1-pre.003` — identités techniques et environnement `KS_*`
|
### `0.5.1-pre.003` — identités techniques `ks-lib-*`
|
||||||
|
|
||||||
- migrer les targets/processor identities généralistes ;
|
- migrer les targets et identités runtime/persistables généralistes ;
|
||||||
- migrer les variables d'environnement ;
|
- synchroniser matrices, tracing, diagnostics et provenance/replay ;
|
||||||
- mettre en place la classification Secret/Public/Internal ;
|
- conserver encore les variables d'environnement pour la prerelease suivante.
|
||||||
- mettre à jour exemples et tests sans encore réinventer le store SQL.
|
|
||||||
|
|
||||||
### `0.5.1-pre.004` — split configuration/logging
|
### `0.5.1-pre.004` — environnement et classification nominale
|
||||||
|
|
||||||
|
- migrer les contrats Solana vers `KS_*` et réserver `KB_*` aux futurs contrats Bot ;
|
||||||
|
- classer les secrets en `*_SECRET_*`, les valeurs explicitement publiques en `*_PUBLIC_*` et le reste en interne ;
|
||||||
|
- consolider les alias historiques Token-2022 ;
|
||||||
|
- mettre à jour `.env.example`, configuration, fixtures, scénarios, store, desktop et guides ;
|
||||||
|
- ne pas encore implémenter le camouflage ou la propagation de sensibilité.
|
||||||
|
|
||||||
|
### `0.5.1-pre.005` — split configuration/logging
|
||||||
|
|
||||||
- documents et schémas indépendants ;
|
- documents et schémas indépendants ;
|
||||||
- profils logging indépendants ;
|
- profils logging indépendants ;
|
||||||
- propriété unique des contrats logging ;
|
- propriété unique des contrats logging ;
|
||||||
- migration/compatibilité explicite des fichiers `0.5.0`.
|
- migration/compatibilité explicite du document monolithique précédent.
|
||||||
|
|
||||||
### `0.5.1-pre.005` — runtime/public et Tauri sûr
|
### `0.5.1-pre.006` — runtime/public, camouflage et Tauri sûr
|
||||||
|
|
||||||
- séparer source/runtime/public ;
|
- séparer source/runtime/public/diagnostic ;
|
||||||
|
- propager la sensibilité des valeurs composées ;
|
||||||
- supprimer les payloads de config complète ;
|
- supprimer les payloads de config complète ;
|
||||||
- diagnostics sûrs ;
|
- diagnostics sûrs et camouflage systématique ;
|
||||||
- tests de non-divulgation ;
|
- tests de non-divulgation et TS-RS aligné.
|
||||||
- TS-RS aligné.
|
|
||||||
|
|
||||||
### `0.5.1-pre.006` — réconciliation et clôture
|
### `0.5.1-pre.007` — réconciliation et clôture
|
||||||
|
|
||||||
- audit exhaustif des anciens préfixes ;
|
- audit exhaustif des anciens préfixes ;
|
||||||
- documentation finale ;
|
- documentation finale ;
|
||||||
@@ -367,7 +351,7 @@ Le détail doit être confirmé par `0.5.1-pre.001`, mais la trajectoire cible e
|
|||||||
- archivage du plan/prompt ;
|
- archivage du plan/prompt ;
|
||||||
- préparation de `0.5.2`.
|
- préparation de `0.5.2`.
|
||||||
|
|
||||||
Ce découpage peut évoluer si `pre.001` démontre qu'une étape doit être scindée pour garder chaque prerelease compilable et bornée.
|
Ce découpage reste borné : aucun chantier SQL `k_sol_*`, wallet ou DEX n'est absorbé dans `0.5.1`.
|
||||||
|
|
||||||
## Règles de développement à conserver
|
## Règles de développement à conserver
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# file: scripts/audit_khadhroony_workspace_rules.py
|
# file: scripts/audit_khadhroony_workspace_rules.py
|
||||||
# version: 19
|
# version: 20
|
||||||
|
|
||||||
"""Audit mechanically verifiable rules specific to khadhroony-bot3."""
|
"""Audit mechanically verifiable rules specific to khadhroony-bot3."""
|
||||||
|
|
||||||
@@ -864,6 +864,83 @@ def audit_private_ks_lib_paths_in_active_docs(root: pathlib.Path) -> list[Violat
|
|||||||
return violations
|
return violations
|
||||||
|
|
||||||
|
|
||||||
|
def audit_environment_namespaces(root: pathlib.Path) -> list[Violation]:
|
||||||
|
"""Require workspace-owned environment variables to use KS_* or KB_* namespaces."""
|
||||||
|
|
||||||
|
violations: list[Violation] = []
|
||||||
|
rust_pattern = re.compile(
|
||||||
|
r'std::env::(?:var|var_os|set_var|remove_var)\(\s*"([A-Z][A-Z0-9_]*)"'
|
||||||
|
)
|
||||||
|
rust_roots = [path.parent for path in sorted(root.glob("ks-*/Cargo.toml"))]
|
||||||
|
desktop = root / "kb-app-demo-desktop"
|
||||||
|
if desktop.is_dir():
|
||||||
|
rust_roots.append(desktop)
|
||||||
|
for rust_root in rust_roots:
|
||||||
|
for path in sorted((rust_root / "src").rglob("*.rs")):
|
||||||
|
relative = path.relative_to(root).as_posix()
|
||||||
|
text = path.read_text(encoding="utf-8")
|
||||||
|
for match in rust_pattern.finditer(text):
|
||||||
|
name = match.group(1)
|
||||||
|
if name.startswith(("KS_", "KB_")):
|
||||||
|
continue
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_ENV001",
|
||||||
|
relative,
|
||||||
|
text[: match.start()].count("\n") + 1,
|
||||||
|
f"workspace-owned environment variable `{name}` must use a `KS_*` or `KB_*` namespace",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
env_example = root / ".env.example"
|
||||||
|
if env_example.is_file():
|
||||||
|
assignment = re.compile(r"^\s*#?\s*([A-Z][A-Z0-9_]*)=")
|
||||||
|
for index, line in enumerate(env_example.read_text(encoding="utf-8").splitlines(), 1):
|
||||||
|
match = assignment.match(line)
|
||||||
|
if match is None or match.group(1).startswith(("KS_", "KB_")):
|
||||||
|
continue
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_ENV002",
|
||||||
|
".env.example",
|
||||||
|
index,
|
||||||
|
f"workspace environment example `{match.group(1)}` must use a `KS_*` or `KB_*` namespace",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
config = root / "config/example.config.json"
|
||||||
|
if config.is_file():
|
||||||
|
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_")):
|
||||||
|
continue
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_ENV003",
|
||||||
|
"config/example.config.json",
|
||||||
|
text[: match.start()].count("\n") + 1,
|
||||||
|
f"configuration placeholder `{name}` must use a `KS_*` or `KB_*` namespace",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
guide = root / "docs/DEVNET_EXECUTION_GUIDE.md"
|
||||||
|
if guide.is_file():
|
||||||
|
text = guide.read_text(encoding="utf-8")
|
||||||
|
exported = re.compile(r"\bexport\s+([A-Z][A-Z0-9_]*)=")
|
||||||
|
for match in exported.finditer(text):
|
||||||
|
name = match.group(1)
|
||||||
|
if name.startswith(("KS_", "KB_")):
|
||||||
|
continue
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_ENV004",
|
||||||
|
"docs/DEVNET_EXECUTION_GUIDE.md",
|
||||||
|
text[: match.start()].count("\n") + 1,
|
||||||
|
f"operator environment variable `{name}` must use a `KS_*` or `KB_*` namespace",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return violations
|
||||||
|
|
||||||
|
|
||||||
def audit_wincode_resolution(root: pathlib.Path) -> list[Violation]:
|
def audit_wincode_resolution(root: pathlib.Path) -> list[Violation]:
|
||||||
"""Require the currently compatible Solana wincode dependency family."""
|
"""Require the currently compatible Solana wincode dependency family."""
|
||||||
|
|
||||||
@@ -946,6 +1023,7 @@ def main() -> int:
|
|||||||
+audit_token_2022_naming(root)
|
+audit_token_2022_naming(root)
|
||||||
+audit_private_ks_lib_paths_in_active_docs(root)
|
+audit_private_ks_lib_paths_in_active_docs(root)
|
||||||
+audit_solana_types(root)
|
+audit_solana_types(root)
|
||||||
|
+audit_environment_namespaces(root)
|
||||||
+audit_wincode_resolution(root)
|
+audit_wincode_resolution(root)
|
||||||
)
|
)
|
||||||
violations.sort(key=lambda item: (item.code, item.path, item.line, item.message))
|
violations.sort(key=lambda item: (item.code, item.path, item.line, item.message))
|
||||||
|
|||||||
Reference in New Issue
Block a user