v0.4.8-pre.013

This commit is contained in:
2026-08-08 22:28:17 +02:00
parent f5efce576b
commit 8b831f8692
77 changed files with 15590 additions and 1585 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: kb-pipeline-demo-scenarios/USAGE.md -->
<!-- version: 12 -->
<!-- version: 24 -->
# Utilisation de kb-pipeline-demo-scenarios
@@ -115,7 +115,7 @@ cargo test -p kb-pipeline-demo-scenarios optional_devnet_token_2022_metadata_cam
`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.
La sortie `TOKEN_2022_METADATA_FIXTURE` conserve le mint et la signature de préparation. Chaque ligne `TOKEN_2022_METADATA_STEP` conserve lopération, la signature, le slot, la postcondition, le nombre de matérialisations et, pour `Emit`, la taille du `returnData`. Ces preuves doivent être reportées dans `SPL_TOKEN_2022_METADATA_DEVNET_VALIDATION_MATRIX.json` et dans le rapport `V0_4_8_PRE_012_TOKEN_2022_METADATA_DEVNET_VALIDATION_REPORT.md` ; elles ne sont jamais préremplies avant lexécution réelle.
La sortie `TOKEN_2022_METADATA_FIXTURE` conserve le mint et la signature de préparation. Chaque ligne `TOKEN_2022_METADATA_STEP` conserve lopé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 `V0_4_8_PRE_012_TOKEN_2022_METADATA_DEVNET_VALIDATION_REPORT.md`. Une nouvelle exécution produit de nouvelles transactions et ne remplace ces preuves quaprès validation explicite.
## Charger la matrice de validation Token-2022
@@ -308,12 +308,14 @@ cargo test -p kb-pipeline-demo-scenarios optional_devnet_current_operation_from_
Variables optionnelles :
- `KB_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 lhydratation canonique, lextraction Core, le replay et la vérification didempotence après une soumission ;
- `KB_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 ;
- `KB_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 ;
- `KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1` pour confirmer explicitement la soumission.
La soumission reste impossible si les deux dernières variables ne sont pas activées. Les opérations dépréciées sont rejetées avant tout appel RPC.
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 lextraction 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
@@ -354,6 +356,124 @@ fn creator_verify_request(
`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 dexiger de longs JSON écrits à la main.
## Préparer `Create` puis `Mint` avec un ATA canonique
`prepare_metaplex_create_fixture` prépare maintenant une base réseau commune aux cinq familles : un mint SPL classique frais et lATA canonique de lopérateur sont créés dans une même transaction native, puis relus et validés. La supply du mint et le solde de lATA doivent rester à zéro à cette étape afin que lopération Metaplex `Mint` constitue la preuve de création de supply.
Le résumé expose notamment :
- `token_account`, lATA classique canonique ;
- `token_record`, renseigné uniquement pour le pNFT ;
- `mint_amount_raw`, égal à `1` pour NFT/collection/pNFT, `10` pour SFT et `1_000_000_000` pour le fungible à 9 décimales ;
- `operation_json`, lintent `Create` typé ;
- `mint_operation_json`, lintent `Mint` typé à exécuter seulement après confirmation de `Create`.
Le token record pNFT est uniquement dérivé pendant la préparation. Sa création reste la responsabilité de `Mint`, de sorte que la fixture ne fabrique pas à lavance létat que la campagne doit démontrer.
## Exécuter la campagne Devnet `Create -> Mint`
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 lATA 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 lopé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 lalias `pnft`.
```bash
KB_DEVNET_METAPLEX_CREATE_MINT_CAMPAIGN_TEST=1 \
KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
KB_DEVNET_METAPLEX_CREATE_MINT_FAMILY=nft \
KB_POSTGRES_TEST_URL='postgresql://…' \
cargo test -p kb-pipeline-demo-scenarios \
optional_devnet_metaplex_create_mint_campaign_from_env \
-- --nocapture
```
La sortie `METAPLEX_CREATE_MINT_FIXTURE` conserve les comptes de la fixture. Deux lignes `METAPLEX_CREATE_MINT_STEP` exposent ensuite les signatures/slots de `Create` et `Mint`, les matérialisations, la transition supply/amount et les états bruts de lATA avant/après `Mint`. Ces valeurs doivent être conservées avant de promouvoir une ligne de la matrice réseau.
## Exécuter la campagne collection `Verify -> Unverify`
`execute_devnet_metaplex_collection_verify_campaign` réutilise les fixtures `Create -> Mint` qualifiées pour construire un Collection NFT parent et un NFT membre lié au parent avec `verified=false`. Le runner exécute ensuite les wrappers courants `Verify(CollectionV1)` puis `Unverify(CollectionV1)`.
La preuve stateful exige simultanément :
- `collection.verified` du membre : `false -> true -> false` ;
- `CollectionDetails::V1.size` du parent : `0 -> 1 -> 0` ;
- Metadata PDA membre et parent présentes ;
- Master Edition parent présente ;
- hydratation canonique, Core extraction, replay, matérialisation et idempotence propres pour `Verify` et `Unverify`.
Le parcours ne soumet pas `SetCollectionSize` : cette opération est obsolète et ne doit pas fabriquer artificiellement la postcondition de taille.
```bash
KB_DEVNET_METAPLEX_COLLECTION_VERIFY_CAMPAIGN_TEST=1 \
KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
KB_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
cargo test -p kb-pipeline-demo-scenarios \
optional_devnet_metaplex_collection_verify_campaign_from_env \
-- --nocapture
```
Une exécution réussie imprime `METAPLEX_COLLECTION_VERIFY_FIXTURE`, deux lignes `METAPLEX_COLLECTION_VERIFY_STEP`, létat fermé `METAPLEX_COLLECTION_VERIFY_STATE` et une ligne machine-readable `METAPLEX_COLLECTION_VERIFY_EVIDENCE`. La campagne qualifiante a été conservée sous `pre.013` ; `Verify` et `Unverify` sont désormais `confirmed` sur la famille `collection` dans la matrice Devnet.
## Exécuter la campagne pNFT `Delegate -> Lock -> Unlock -> Revoke -> Delegate -> Transfer`
`execute_devnet_metaplex_pnft_lifecycle_campaign` crée dabord une fixture `programmable_nft` fraîche via la campagne `Create -> Mint` qualifiée. Il crée ensuite un wallet temporaire de delegate et un propriétaire destination frais, puis enchaîne deux rôles de Token Delegate distincts :
1. `Delegate(StakingV1)` par le propriétaire ;
2. `Lock` puis `Unlock` par le staking delegate ;
3. `Revoke(StakingV1)` par le propriétaire ;
4. `Delegate(TransferV1)` par le propriétaire ;
5. `Transfer` par le transfer delegate vers une ATA destination fraîche.
Le runner exige que le Token Record source passe `Unlocked/Staking -> Locked/Staking -> Unlocked/Staking -> delegate cleared -> Unlocked/Transfer`. Après le transfert, lATA source doit contenir `0` et rester `Initialized`, tandis que lATA 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 lexigent.
```bash
KB_DEVNET_METAPLEX_PNFT_LIFECYCLE_CAMPAIGN_TEST=1 \
KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
KB_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
cargo test -p kb-pipeline-demo-scenarios \
optional_devnet_metaplex_pnft_lifecycle_campaign_from_env \
-- --nocapture
```
Une exécution qualifiante doit terminer `ok` et produire `METAPLEX_PNFT_LIFECYCLE_FIXTURE`, six lignes `METAPLEX_PNFT_LIFECYCLE_STEP`, `METAPLEX_PNFT_LIFECYCLE_STATE` et `METAPLEX_PNFT_LIFECYCLE_EVIDENCE`. Le bundle qualifiant a été observé sous `pre.013` ; `Delegate`, `Revoke`, `Lock`, `Unlock` et `Transfer` sont désormais `confirmed` sur `programmable_nft`.
## Campagne Devnet Metaplex Token Owned 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 lATA de lopérateur puis ferme le compte escrow.
```bash
KB_DEVNET_METAPLEX_ESCROW_CAMPAIGN_TEST=1 \
KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
KB_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
cargo test -p kb-pipeline-demo-scenarios \
optional_devnet_metaplex_escrow_campaign_from_env \
-- --nocapture
```
Une exécution qualifiante doit produire `METAPLEX_ESCROW_FIXTURE`, deux lignes `METAPLEX_ESCROW_SETUP`, trois lignes `METAPLEX_ESCROW_STEP`, `METAPLEX_ESCROW_STATE` et `METAPLEX_ESCROW_EVIDENCE`. Le bundle complet a été observé sous `pre.013` ; `CreateEscrowAccount`, `TransferOutOfEscrow` et `CloseEscrowAccount` sont désormais `confirmed` sur la famille `nft`.
## Campagne Devnet Metaplex maintenance
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
KB_DEVNET_METAPLEX_MAINTENANCE_CAMPAIGN_TEST=1 \
KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
KB_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
cargo test -p kb-pipeline-demo-scenarios \
optional_devnet_metaplex_maintenance_campaign_from_env \
-- --nocapture
```
Le bundle qualifiant de `pre.013` confirme `Update` et conserve les refus runtime exacts suivants :
- `Resize` : `Custom(201)`, compte déjà au layout cible ;
- `Migrate` : `Custom(75)`, instruction retirée ;
- `Collect` : `Custom(7)`, autorité de collecte Metaplex réservée ;
- `CloseAccounts` : `Custom(188)`, autorité ownerless-close Metaplex réservée.
Le bilan courant de la matrice Devnet Metaplex est **15 `confirmed`, 5 `unavailable`, 0 `not_run`**. Les campagnes restent réexécutables pour diagnostiquer une régression ou un changement de runtime, mais ne constituent plus des tâches ouvertes de `pre.013`.
## Solana Program Metadata
Linventaire fermé est exposé par :
@@ -403,4 +523,23 @@ where
Cet appel crée des comptes et soumet onze transactions réelles au minimum : deux transferts de préfinancement et neuf opérations `ProgM6…`. Il ne doit jamais être déclenché implicitement par une ouverture de fenêtre ou une simple demande de simulation.
La matrice `SOLANA_PROGRAM_METADATA_DEVNET_VALIDATION_MATRIX.json` reste à `not_run` tant que les signatures, simulations, postconditions et preuves matérialisées nont pas été enregistrées. `Close` exige une preuve `account_absence`, car un compte absent ne produit pas de snapshot matérialisé.
### Preuve machine-readable `Create -> Mint`
À partir de `pre.013-delta-fix-012`, une campagne réussie imprime en plus une ligne unique `METAPLEX_CREATE_MINT_EVIDENCE`. Elle contient les deux objets `create` et `mint` avec le cluster, le genesis hash, le slot RPC de simulation, le nombre de logs, le message hash exact, le fee estimé, la signature, le statut/slot de confirmation, les nombres de snapshots et matérialisations ainsi que les drapeaux canonical/Core/replay/idempotence. Cette ligne est la forme à conserver pour les futures promotions de matrice.
Les cinq familles NFT, SFT, fungible, collection et pNFT sont confirmées. `Create` et `Mint` disposent chacune de cinq bundles `familyEvidence`; le pNFT prouve en plus la création du Token Record et létat ATA `Initialized(1) -> Frozen(2)`.
## Probe Devnet Metaplex `Use`
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
KB_DEVNET_METAPLEX_USE_PROBE_TEST=1 \
KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1 \
KB_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
cargo test -p kb-pipeline-demo-scenarios \
optional_devnet_metaplex_use_probe_from_env \
-- --nocapture
```
Une simulation négative est retournée comme résultat uniquement lorsque `submit=false`. Elle ne peut jamais autoriser une signature ou une soumission.