v0.2.5-pre.009

This commit is contained in:
2026-08-20 09:24:10 +02:00
parent 1125ade4c1
commit e91bf36e9e
83 changed files with 2467 additions and 1801 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/000-README.md -->
<!-- version: 36 -->
<!-- version: 37 -->
# Documentation KSP
@@ -56,7 +56,8 @@ docs/
│ ├── 004-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER.md
│ ├── 005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md
│ ├── 006-V0_2_3_HTTP_TRANSACTIONS.md
── 007-V0_2_4_HTTP_FINAL_COMPLIANCE.md
── 007-V0_2_4_HTTP_FINAL_COMPLIANCE.md
│ └── 008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md
└── rules/
├── FILE_CONTRACTS.md
├── PROMPT_STRUCTURE.md
@@ -73,11 +74,11 @@ D'autres sous-répertoires seront ajoutés uniquement lorsque leur rôle aura é
## Documents de planification
Le plan historique de la phase fondatrice clôturée est conservé dans [`plans/001-V0_0_3_PLAN.md`](plans/001-V0_0_3_PLAN.md). La séquence active des premières releases fonctionnelles est définie dans [`plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md`](plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md). Le plan détaillé de la release stable `0.1.1` est conservé comme historique clôturé dans [`plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md`](plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.2` est conservé comme historique clôturé dans [`plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md`](plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.3 — Configuration foundation` est conservé comme historique clôturé dans [`plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md`](plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.4 — ksp-app-config-desk` est conservé comme historique clôturé dans [`plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md`](plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md), avec sa matrice finale [`validation/001-V0_1_4_CONFIG_DESKTOP.md`](validation/001-V0_1_4_CONFIG_DESKTOP.md). Son prompt d'ouverture historique reste [`../prompts/004-V0_1_4_START_PROMPT.md`](../prompts/004-V0_1_4_START_PROMPT.md). La release stable `0.2.0` clôt l'audit de bot3 et le découpage de la série. Son plan directeur est conservé comme historique clôturé dans [`plans/007-V0_2_0_SERIES_PLANNING.md`](plans/007-V0_2_0_SERIES_PLANNING.md), avec sa matrice finale [`validation/002-V0_2_0_SERIES_PLANNING.md`](validation/002-V0_2_0_SERIES_PLANNING.md). La release stable `0.2.1 — HTTP Solana foundation` a été ouverte par [`../prompts/006-V0_2_1_START_PROMPT.md`](../prompts/006-V0_2_1_START_PROMPT.md). Son gate de sizing et sa matrice exhaustive sont conservés dans [`plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md`](plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md), avec la validation finale [`validation/003-V0_2_1_ONCHAIN_HTTP.md`](validation/003-V0_2_1_ONCHAIN_HTTP.md), README/USAGE Transport et le smoke Devnet opt-in de composition Config -> Transport. Le prompt [`../prompts/007-V0_2_2_START_PROMPT.md`](../prompts/007-V0_2_2_START_PROMPT.md) a ouvert la release stable `0.2.2 — HTTP Accounts + Tokens + Cluster`. Son plan clôturé [`plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md`](plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md) conserve l'audit et l'implémentation des 22 wrappers typés, tandis que [`validation/004-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER.md`](validation/004-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER.md) enregistre les validations déterministes, les graphes Cargo et les deux smokes Devnet passés avant publication. Le prompt [`../prompts/008-V0_2_3_START_PROMPT.md`](../prompts/008-V0_2_3_START_PROMPT.md) a ouvert la release stable `0.2.3 — HTTP Transactions`. Son plan clôturé [`plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md`](plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md) conserve l'audit et l'implémentation des 11 wrappers ; le réaudit [`validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md`](validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md) confirme la complétude des 37 wrappers HTTP typés et [`validation/006-V0_2_3_HTTP_TRANSACTIONS.md`](validation/006-V0_2_3_HTTP_TRANSACTIONS.md) enregistre les validations finales, graphes Cargo et deux smokes Devnet passés avant publication. Le prompt [`../prompts/009-V0_2_4_START_PROMPT.md`](../prompts/009-V0_2_4_START_PROMPT.md) a ouvert la release stable `0.2.4 — HTTP Blocks + Economics + compliance HTTP finale`. Son plan clôturé [`plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md`](plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md) conserve limplémentation des 15 wrappers et la compliance `52/52 + 14/14`; la matrice finale [`validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md`](validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md) enregistre le réaudit SIMD/inventaire, les canaries globales et les preuves opérateur avant publication. Le prompt [`../prompts/010-V0_2_5_START_PROMPT.md`](../prompts/010-V0_2_5_START_PROMPT.md), finalisé par `0.2.4-pre.009-fix.001`, ouvre `0.2.5 — Wallet foundation` sur la base stable `v0.2.4`. Son plan actif [`plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md) part du gate `pre.001` (héritage, threat model offline, VIEW/OWNER indépendants et niveau B read-only), puis matérialise la crate en `pre.002`, le wire/transcript en `pre.003`, les primitives Argon2id/XChaCha20-Poly1305 en `pre.004` et, en `pre.005`, les payloads protégés, le profil de création benchmarké, lautorité Ed25519 séparée ainsi que les flux in-memory create/open VIEW/OWNER avec vecteur complet interopérable. `pre.006` porte la persistence atomique/no-clobber.
Le plan historique de la phase fondatrice clôturée est conservé dans [`plans/001-V0_0_3_PLAN.md`](plans/001-V0_0_3_PLAN.md). La séquence active des premières releases fonctionnelles est définie dans [`plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md`](plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md). Le plan détaillé de la release stable `0.1.1` est conservé comme historique clôturé dans [`plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md`](plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.2` est conservé comme historique clôturé dans [`plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md`](plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.3 — Configuration foundation` est conservé comme historique clôturé dans [`plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md`](plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.4 — ksp-app-config-desk` est conservé comme historique clôturé dans [`plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md`](plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md), avec sa matrice finale [`validation/001-V0_1_4_CONFIG_DESKTOP.md`](validation/001-V0_1_4_CONFIG_DESKTOP.md). Son prompt d'ouverture historique reste [`../prompts/004-V0_1_4_START_PROMPT.md`](../prompts/004-V0_1_4_START_PROMPT.md). La release stable `0.2.0` clôt l'audit de bot3 et le découpage de la série. Son plan directeur est conservé comme historique clôturé dans [`plans/007-V0_2_0_SERIES_PLANNING.md`](plans/007-V0_2_0_SERIES_PLANNING.md), avec sa matrice finale [`validation/002-V0_2_0_SERIES_PLANNING.md`](validation/002-V0_2_0_SERIES_PLANNING.md). La release stable `0.2.1 — HTTP Solana foundation` a été ouverte par [`../prompts/006-V0_2_1_START_PROMPT.md`](../prompts/006-V0_2_1_START_PROMPT.md). Son gate de sizing et sa matrice exhaustive sont conservés dans [`plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md`](plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md), avec la validation finale [`validation/003-V0_2_1_ONCHAIN_HTTP.md`](validation/003-V0_2_1_ONCHAIN_HTTP.md), README/USAGE Transport et le smoke Devnet opt-in de composition Config -> Transport. Le prompt [`../prompts/007-V0_2_2_START_PROMPT.md`](../prompts/007-V0_2_2_START_PROMPT.md) a ouvert la release stable `0.2.2 — HTTP Accounts + Tokens + Cluster`. Son plan clôturé [`plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md`](plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md) conserve l'audit et l'implémentation des 22 wrappers typés, tandis que [`validation/004-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER.md`](validation/004-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER.md) enregistre les validations déterministes, les graphes Cargo et les deux smokes Devnet passés avant publication. Le prompt [`../prompts/008-V0_2_3_START_PROMPT.md`](../prompts/008-V0_2_3_START_PROMPT.md) a ouvert la release stable `0.2.3 — HTTP Transactions`. Son plan clôturé [`plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md`](plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md) conserve l'audit et l'implémentation des 11 wrappers ; le réaudit [`validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md`](validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md) confirme la complétude des 37 wrappers HTTP typés et [`validation/006-V0_2_3_HTTP_TRANSACTIONS.md`](validation/006-V0_2_3_HTTP_TRANSACTIONS.md) enregistre les validations finales, graphes Cargo et deux smokes Devnet passés avant publication. Le prompt [`../prompts/009-V0_2_4_START_PROMPT.md`](../prompts/009-V0_2_4_START_PROMPT.md) a ouvert la release stable `0.2.4 — HTTP Blocks + Economics + compliance HTTP finale`. Son plan clôturé [`plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md`](plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md) conserve limplémentation des 15 wrappers et la compliance `52/52 + 14/14`; la matrice finale [`validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md`](validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md) enregistre le réaudit SIMD/inventaire, les canaries globales et les preuves opérateur avant publication. Le prompt [`../prompts/010-V0_2_5_START_PROMPT.md`](../prompts/010-V0_2_5_START_PROMPT.md), finalisé par `0.2.4-pre.009-fix.001`, ouvre `0.2.5 — Wallet foundation` sur la base stable `v0.2.4`. Son plan actif [`plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md) part du gate `pre.001` (héritage, threat model offline, VIEW/OWNER indépendants et niveau B read-only), puis matérialise la crate en `pre.002`, le wire/transcript en `pre.003`, les primitives Argon2id/XChaCha20-Poly1305 en `pre.004`, les payloads/create/open en `pre.005`, la persistence en `pre.006`, l'administration/signature en `pre.007` et les adapters transfer en `pre.008`. `pre.009` ferme l'audit adversarial/interoperability/compliance dans [`validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md`](validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md) avant la documentation finale `pre.010`.
## Spécifications de formats
Les formats durables, interopérables et destinés à être réimplémentables hors de KSP sont indexés depuis [`formats/000-README.md`](formats/000-README.md). Le premier format natif publié dans cette famille est [`.kspwallet` V1](formats/KSPWALLET_V1.md) : `pre.003` en fige le wire/transcript/AAD, `pre.004` les primitives KDF/AEAD et `pre.005` les payloads plaintext, lautorité Ed25519 OWNER, les procédures create/open VIEW/OWNER, le profil de création KSP issu du benchmark et un vecteur complet interopérable indépendant du code Rust.
Les formats durables, interopérables et destinés à être réimplémentables hors de KSP sont indexés depuis [`formats/000-README.md`](formats/000-README.md). Le premier format natif publié dans cette famille est [`.kspwallet` V1](formats/KSPWALLET_V1.md) : `pre.003` en fige le wire/transcript/AAD, `pre.004` les primitives KDF/AEAD, `pre.005` les payloads/autorité OWNER/vecteur complet, `pre.006``pre.008` les flux persistence/administration/transfert, et `pre.009` l'audit adversarial ainsi que la reproduction externe des vecteurs avant clôture documentaire.
`IDEAS.md` conserve les pistes et questions qui ne sont pas encore des engagements du roadmap ni des décisions architecturales.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/formats/000-README.md -->
<!-- version: 3 -->
<!-- version: 4 -->
# Formats KSP
@@ -9,4 +9,4 @@ Une spécification de format décrit le wire exact, les encodages, les limites,
## Formats actifs
- [`KSPWALLET_V1.md`](KSPWALLET_V1.md) — spécification du format natif autonome `.kspwallet` V1. `0.2.5-pre.003` fige l'enveloppe/wire et les transcripts/AAD, `pre.004` ajoute Argon2id/XChaCha20-Poly1305/CSPRNG OS et `pre.005` fixe les payloads plaintext, le profil de création KSP calibré, l'autorité Ed25519 OWNER, les procédures create/open VIEW/OWNER et un vecteur complet interopérable test-only.
- [`KSPWALLET_V1.md`](KSPWALLET_V1.md) — spécification du format natif autonome `.kspwallet` V1. `0.2.5-pre.003` fige l'enveloppe/wire et les transcripts/AAD, `pre.004` ajoute Argon2id/XChaCha20-Poly1305/CSPRNG OS, `pre.005` fixe les payloads plaintext, le profil de création KSP calibré, l'autorité Ed25519 OWNER et le vecteur complet, `pre.006``pre.008` matérialisent persistence/administration/transfert, et `pre.009` clôt l'audit adversarial/interoperabilité/compliance avant la documentation finale.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/formats/KSPWALLET_V1.md -->
<!-- version: 6 -->
<!-- version: 7 -->
# `.kspwallet` V1 — spécification du format natif Wallet KSP
@@ -988,3 +988,53 @@ La première retourne au caller des octets contenant volontairement le secret et
Les exports Base58 et Solana CLI JSON doivent reconstruire exactement la même keypair et la même Pubkey que le wallet OWNER source.
## 25. Audit security/interoperability `pre.009`
`0.2.5-pre.009` n'ajoute aucun octet au wire V1 et ne change aucun algorithme. La tranche ferme le gate technique par des canaris adversariaux, une reproduction externe des vecteurs et un audit du graphe Cargo.
Les canaris exécutables vérifient notamment :
```text
tampering canonique du slot OWNER / owner-control / metadata / secret / state_signature
-> wallet.authentication_failed avant unlock
state_signature invalide + password vide
-> wallet.authentication_failed avant Argon2
changement du ciphertext de wrapping VIEW uniquement
-> signature OWNER toujours valide
-> OWNER reste ouvrable
-> VIEW échoue avec wallet.view_unlock_failed
wrong OWNER / wrong VIEW
-> erreurs génériques dédiées
-> aucun password reflété dans Display/Debug
public API
-> aucun re-export solana-keypair / solana-signer / solana-signature
-> aucune surface sign/export sur WalletView
```
Le vecteur complet publié en section 22 a été reproduit indépendamment du code Rust KSP avec une sonde externe :
```text
Argon2id v19 dérivations OWNER et VIEW exactes
XChaCha20-Poly1305 vecteur de wrapping pre.004 exact
Ed25519 state_signature exacte vérifiée sur state_transcript
Base58 keypair 64 octets et Pubkey attendue reproduites
```
Cette sonde n'est pas une dépendance KSP et n'est pas requise au runtime ; elle sert uniquement de preuve d'interopérabilité indépendante.
Le profil de création `64 MiB / 3 / 1` est cohérent avec la seconde recommandation Argon2id de RFC 9106 pour les environnements contraints. Les paramètres restent sérialisés par slot afin que les futurs defaults puissent évoluer sans rendre les wallets existants illisibles. XChaCha20-Poly1305 conserve une clé 256 bits et un nonce 192 bits généré par le CSPRNG OS. Les signatures d'état utilisent Ed25519 au format 64 octets défini par RFC 8032.
Le graphe Cargo observé au gate `pre.008` conserve une seule génération `ed25519-dalek 2.2.0`, une seule `solana-address 2.7.0` et un unique parent KSP direct de `solana-keypair 3.1.2` : `ksp-wallet-lib`. Les doublons `digest 0.10/0.11`, `crypto-common 0.1/0.2`, `block-buffer 0.10/0.12`, `cpufeatures 0.2/0.3`, `getrandom 0.3/0.4`, `rand 0.9/0.10`, `rand_core 0.6/0.9/0.10`, `sha2 0.10/0.11` et `syn 2/3` sont transitoires et imposés par les générations actuellement consommées par RustCrypto, Solana et Logging ; KSP n'ajoute pas une deuxième dépendance directe pour les contourner.
Limites explicitement conservées en V1 :
- aucun anti-rollback ni détection d'un remplacement intégral par un autre wallet valide sans ancre externe ;
- aucune promesse de CAS filesystem linéarisable ; l'atomicité réelle dépend de l'OS/filesystem ;
- les permissions `0600` d'export Unix sont une hygiène, pas une garantie cryptographique ;
- la zeroization réduit les copies possédées mais ne constitue pas une preuve d'effacement physique de toute copie potentielle produite par le compilateur, l'OS ou le matériel ;
- aucune revendication de résistance side-channel supplémentaire au-delà des primitives et bibliothèques retenues.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md -->
<!-- version: 11 -->
<!-- version: 12 -->
# Plan `0.2.5` — Wallet foundation
@@ -382,7 +382,7 @@ La génération SDK récente définit `Pubkey` comme alias du type `Address`, ma
Un `cargo tree` est obligatoire avec `pre.005` afin de confirmer l'unification de `solana-address`, `ed25519-dalek`, `rand/getrandom` et d'éviter des duplications crypto injustifiées.
Audit source notable : `solana-keypair 3.1.2` contient un bloc `unsafe` interne dans sa conversion Base58 vers `String`. Cela ne modifie pas la règle `#![forbid(unsafe_code)]` du code KSP, mais doit rester visible dans l'audit des transitifs ; `pre.008` réévaluera le chemin Base58 réellement appelé et les alternatives avant de figer l'adapter.
Audit source notable : `solana-keypair 3.1.2` contient un bloc `unsafe` interne dans sa conversion Base58 vers `String`. Cela ne modifie pas la règle `#![forbid(unsafe_code)]` du code KSP. `pre.008` conserve finalement le codec maintenu par `solana-keypair` au lieu d'ajouter un second codec `bs58` direct ; `pre.009` classe donc cet `unsafe` comme implémentation upstream auditée, sans `unsafe` KSP et sans duplication de codec.
### 8.2 KDF
@@ -870,11 +870,11 @@ Pas de full path/filename par défaut dans les logs Wallet ; le caller peut corr
### 17.1 Architecture
Le cœur ne doit pas utiliser un enum central fermé qui oblige à modifier toutes les branches à chaque nouveau format.
Le cœur ne doit pas figer les consumers sur une liste exhaustive de formats. `pre.008` matérialise donc `WalletTransferFormat` en enum public `#[non_exhaustive]`, avec codes stables et sélection explicite du format par le caller. De nouveaux formats built-in peuvent être ajoutés sans rendre les matches downstream exhaustifs.
`pre.008` doit introduire un contrat d'adapter/descriptor ouvert avec un code stable et des implémentations built-in enregistrables. L'import et l'export sont séparables pour qu'un format read-only n'implémente pas artificiellement l'autre sens.
Le gate `pre.009` renonce volontairement à un trait/plugin public arbitraire de codec V1 : une implémentation externe d'import/export devrait nécessairement recevoir ou retourner les 64 octets secrets de la keypair, ce qui créerait une nouvelle surface publique de key material contraire à l'encapsulation Wallet. Si un besoin réel d'adapters externes apparaît, il recevra un contrat secret explicite et audité dans une release dédiée ; il n'est pas simulé par une abstraction prématurée.
Toute API d'export qui remet temporairement du key material à un adapter est explicitement OWNER-only, nommée dangereusement et limite la durée de vie de la copie via zeroization. Aucun getter secret général n'est introduit.
L'import et l'export built-in restent séparables conceptuellement. Toute API d'export qui remet temporairement du key material au caller est explicitement OWNER-only et le caller devient responsable de la durée de vie/zeroization de sa copie. Aucun getter secret général n'est introduit.
### 17.2 Formats engagés pour `0.2.5`
@@ -1126,7 +1126,7 @@ Une `fix` ou tranche supplémentaire est préférable à la suppression d'une ga
## 22. Dépendances par tranche
État réellement acquis au terme de `pre.007` :
État réellement acquis au terme de `pre.009` :
```text
pre.002 zeroize ^1.9
@@ -1139,18 +1139,21 @@ pre.005 ed25519-dalek ^2.2
tokio déjà workspace, feature locale rt pour spawn_blocking
pre.006 tempfile ^3.27
pre.007 aucune nouvelle dépendance tierce
pre.008 aucune nouvelle dépendance tierce
pre.009 aucune nouvelle dépendance tierce
```
Toutes les dépendances tierces communes restent centralisées sous `[workspace.dependencies]`; le membre Wallet active uniquement les features nécessaires. `ed25519-dalek ^2.2` est volontairement aligné avec la contrainte `^2.1.1` de `solana-keypair 3.1.2` afin de permettre une seule génération Dalek et d'activer `zeroize` sur la `SigningKey` partagée par résolution Cargo.
Candidates restantes, à réauditer juste avant insertion :
Dépendances réauditées mais **non retenues directement** en `0.2.5` :
```text
solana-signer ^3.0 # seulement si un contrat public/impl l'exige réellement
solana-signature ^3.5 # seulement si un type public futur l'exige réellement
solana-signer # aucune API publique Wallet n'exige le trait externe
solana-signature # la signature publique reste [u8; 64]
bs58 # le codec Base58 maintenu par solana-keypair suffit
```
`pre.007` confirme qu'une signature Solana publique peut rester un `[u8; 64]` KSP sans ajouter `solana-signature` à la surface publique. `solana-keypair` reste propriétaire de Wallet : Core continue de réexporter uniquement la `Pubkey` transversale et ne devient pas propriétaire d'un secret/signing capability.
`pre.007` confirme qu'une signature Solana publique peut rester un `[u8; 64]` KSP sans ajouter `solana-signature` à la surface publique. `pre.008` confirme qu'aucun `bs58` direct n'est nécessaire. `solana-keypair` reste propriétaire de Wallet : Core continue de réexporter uniquement la `Pubkey` transversale et ne devient pas propriétaire d'un secret/signing capability.
Déjà présents et réutilisés :
@@ -1255,4 +1258,4 @@ Une future `format_version >= 2` pourra réétudier des facteurs/ancrages extern
## 26. Suite immédiate
`0.2.5-pre.003` fige le codec JSON strict, les limites structurelles, `slot_id` 16 octets, le descripteur VIEW, les DTOs denveloppe/key slots, les TLV transcript/AAD et la première spécification `docs/formats/KSPWALLET_V1.md`. `pre.004` ajoute Argon2id/XChaCha20-Poly1305/CSPRNG OS et le wrapping de content keys. Le benchmark opérateur permet à `pre.005` de retenir le profil initial `64 MiB / 3 / 1`, de figer les payloads `owner_control`/metadata/secret, d'introduire l'autorité Ed25519 OWNER distincte de la keypair Solana et de publier un vecteur complet. `pre.006` ajoute la persistence no-clobber et les ouvertures fichier. `pre.007` ajoute signature Solana, administration metadata, rotations OWNER/VIEW, révocation forte VIEW et remplacement administratif contrôlé. `pre.008` ajoute maintenant les adapters import/export Solana CLI JSON et keypair Base58 complet, l'inspection sûre, l'import vers un nouveau `.kspwallet` no-clobber et l'export OWNER explicite sans `bs58` direct. **La suite immédiate est `pre.009` : audit adversarial/security/compliance et graphes Cargo**, avant la documentation finale `pre.010`.
`0.2.5-pre.003` fige le codec JSON strict, les limites structurelles, `slot_id` 16 octets, le descripteur VIEW, les DTOs denveloppe/key slots, les TLV transcript/AAD et la première spécification `docs/formats/KSPWALLET_V1.md`. `pre.004` ajoute Argon2id/XChaCha20-Poly1305/CSPRNG OS et le wrapping de content keys. Le benchmark opérateur permet à `pre.005` de retenir le profil initial `64 MiB / 3 / 1`, de figer les payloads `owner_control`/metadata/secret, d'introduire l'autorité Ed25519 OWNER distincte de la keypair Solana et de publier un vecteur complet. `pre.006` ajoute la persistence no-clobber et les ouvertures fichier. `pre.007` ajoute signature Solana, administration metadata, rotations OWNER/VIEW, révocation forte VIEW et remplacement administratif contrôlé. `pre.008` ajoute les adapters import/export Solana CLI JSON et keypair Base58 complet, l'inspection sûre, l'import vers un nouveau `.kspwallet` no-clobber et l'export OWNER explicite sans `bs58` direct. `pre.009` ajoute maintenant les canaris adversariaux, formalise les règles Wallet durables, reproduit les vecteurs hors Rust/KSP et audite le graphe Cargo/les duplications transitoires. **La suite immédiate est `pre.010` : documentation finale, README/USAGE Wallet, candidate de clôture et prompt `0.2.6`.**

View File

@@ -1,5 +1,5 @@
<!-- file: docs/rules/RULES_KSP.md -->
<!-- version: 33 -->
<!-- version: 34 -->
# Règles spécifiques à KSP
@@ -76,6 +76,12 @@
## Wallet
- **KSP-WALLET-001** — KSP ne crée pas de `ksp-wallet-api` dans l'architecture actuelle ; `ksp-wallet-lib` possède le format wallet KSP et ses capacités de lecture/protection/import/export/pubkey/secret/signature.
- **KSP-WALLET-002** — `.kspwallet` V1 est autonome : le fichier et le password de la capability concernée suffisent au parsing, à la vérification et au déverrouillage ; aucun Config, environnement, pepper global, keychain, réseau, OTP ou ancre de confiance externe n'est requis par le format.
- **KSP-WALLET-003** — VIEW et OWNER sont des capabilities cryptographiquement indépendantes. VIEW peut lire Pubkey/alias/notes et tourner uniquement son propre password ; il ne peut ni signer, ni exporter le secret, ni administrer les metadata ou l'état OWNER-controlled.
- **KSP-WALLET-004** — La keypair Solana d'un wallet V1 est immuable après création/import et reste encapsulée dans `ksp-wallet-lib`. La surface publique expose la `Pubkey` via `ksp-core-lib` et une opération OWNER de signature, pas la `solana_keypair::Keypair` brute.
- **KSP-WALLET-005** — Toute création ou import natif est no-clobber. Un import crée un nouveau `.kspwallet` et ne remplace jamais un wallet natif existant ; les replacements sont réservés aux mutations capability-bound explicitement autorisées.
- **KSP-WALLET-006** — `ksp-wallet-lib` ne possède aucun répertoire Wallet par défaut et ne lit ni Config ni environnement pour choisir un chemin ; le caller fournit explicitement les chemins de persistence/import/export.
- **KSP-WALLET-007** — L'état OWNER-controlled V1 est authentifié par une autorité Ed25519 distincte de la keypair Solana. V1 ne prétend pas détecter un remplacement intégral par un autre wallet autonome valide ni un rollback intégral vers une ancienne copie valide ; ces garanties exigeraient une ancre externe hors du format V1.
- **KSP-PROGRAM-007** — Le contrat de préparation d'exécution est nommé conceptuellement `ProgramExecutionPreparer`; il ne signe, ne simule, n'envoie et ne confirme pas une transaction.
- **KSP-PROGRAM-008** — `ksp-program-api` reste ouvert : aucun enum central fermé ne doit imposer une modification de l'API pour ajouter un Program ID externe.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/000-README.md -->
<!-- version: 11 -->
<!-- version: 12 -->
# Validations KSP
@@ -17,3 +17,4 @@ Documents :
- [`006-V0_2_3_HTTP_TRANSACTIONS.md`](006-V0_2_3_HTTP_TRANSACTIONS.md) — matrice finale validée de `0.2.3`, 11 wrappers Transactions, sécurité write/simulation, réaudit 52+14, `KSP-TRANSPORT-007` 37/37, graphes Cargo et deux smokes Devnet passés avant publication stable.
- [`007-V0_2_4_HTTP_FINAL_COMPLIANCE.md`](007-V0_2_4_HTTP_FINAL_COMPLIANCE.md) — matrice finale validée de `0.2.4`, inventaire exact 52 current + 14 Deprecated, preuve typed 52/52, audit SIMD final, `KSP-TRANSPORT-007`, workspace complet et deux smokes Devnet passés avant publication stable.
- [`008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md`](008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md) — matrice security/interoperability/compliance de `0.2.5`, threat model V1, adversarial canaries, reproduction externe des vecteurs, audit de frontières et graphes Cargo Wallet.

View File

@@ -0,0 +1,224 @@
<!-- file: docs/validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md -->
<!-- version: 1 -->
# Validation `0.2.5` — Wallet security / interoperability / compliance
## 1. Objet
Cette matrice ferme le gate technique de `0.2.5-pre.009` avant la documentation finale `pre.010`. Elle ne remplace ni la spécification [`../formats/KSPWALLET_V1.md`](../formats/KSPWALLET_V1.md), ni le threat model du plan [`../plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](../plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md), ni les deltas.
Le verdict recherché porte sur quatre axes :
```text
security/adversarial
interoperability indépendante
frontières KSP
Cargo/dependency compliance
```
## 2. État fonctionnel audité
Au gate `pre.009`, Wallet possède :
```text
format autonome .kspwallet V1
VIEW / OWNER indépendants
Argon2id v19
XChaCha20-Poly1305
CSPRNG OS
content keys séparées OWNER / metadata / secret
Ed25519 distinct pour state_signature OWNER
keypair Solana immuable et encapsulée
create/open VIEW/OWNER
persistence no-clobber
replacement administratif capability-bound
signature Solana OWNER
alias/notes + rotations OWNER/VIEW
strong disable/recreate VIEW
import/export Solana CLI JSON + Base58 keypair 64 octets
```
Aucune dépendance Wallet vers Config, Transport, ExecutionPolicy, Store ou Tauri n'est autorisée.
## 3. Matrice adversariale
| Cas | Résultat attendu | Preuve |
|-----------------------------------------------------|---------------------------------------------------------|-----------------------------------------------------------------------------------------------|
| mutation canonique KDF/wrap OWNER | rejet | `security_tests::owner_signed_regions_reject_canonical_tampering_before_unlock` |
| mutation owner-control | rejet | même canari |
| mutation metadata | rejet | même canari |
| mutation secret | rejet | même canari |
| mutation `state_signature` | rejet | même canari |
| état OWNER-signed invalide + password vide | `wallet.authentication_failed` avant Argon2 | `security_tests::owner_signature_verification_precedes_owner_and_view_password_kdf` |
| mutation des credentials rotatables VIEW uniquement | état OWNER toujours valide, OWNER ouvrable, VIEW rejeté | `security_tests::view_credential_tampering_does_not_forge_owner_state_and_cannot_unlock_view` |
| wrong VIEW | `wallet.view_unlock_failed` générique | tests Wallet + security |
| wrong OWNER | `wallet.owner_unlock_failed` générique | tests Wallet + security |
| password canary dans Display/Debug | absent | `security_tests::unlock_failures_do_not_echo_password_material` |
| metadata plaintext dans wallet verrouillé | absent | `wallet::tests::locked_full_vector_contains_no_authorized_identity_or_metadata_plaintext` |
| stale OWNER handle | `wallet.state_conflict` | administration tests |
| wallet A handle vers wallet B | `wallet.state_conflict` | administration tests |
| écriture interrompue avant publish | ancien/destination absent préservé | persistence fault tests |
| concurrence create no-clobber | exactement un gagnant | persistence concurrency test |
| export secret depuis VIEW | surface publique absente | dependency/public-surface canary |
## 4. Ordre de vérification et anti-oracle
Pour VIEW et OWNER :
```text
parse structurel borné
-> state_signature OWNER
-> seulement ensuite Argon2 du slot demandé
-> unwrap AEAD
-> déchiffrement compartment
-> parsing plaintext protégé
```
Le canari `state_signature invalide + password vide` distingue explicitement cet ordre : si Argon2 était évalué avant l'authentification d'état, l'entrée vide produirait une erreur de paramètres crypto ; le résultat attendu reste `wallet.authentication_failed`.
Les erreurs de password ne distinguent pas KDF, wrapping AEAD ou contenu protégé et ne reflètent pas le password fourni.
## 5. Interopérabilité indépendante
Les fixtures publiques test-only restent :
```text
kspwallet_v1_wire_only.json
kspwallet_v1_crypto_vectors.json
kspwallet_v1_full_vector.json
kspwallet_v1_full_vector_meta.json
```
Une sonde indépendante hors Rust/KSP exécutée pendant `pre.009` reproduit :
```text
Argon2id OWNER derived key = exact
Argon2id VIEW derived key = exact
pre.004 XChaCha wrapped key = exact
pre.004 unwrap content key = exact
Ed25519 state signature = vérifiée sur le transcript exact
Solana keypair Base58 = reproduite depuis 64 octets
Solana Pubkey Base58 = reproduite depuis les 32 octets publics
```
La sonde utilise Python avec Argon2 et Ed25519/ChaCha20-Poly1305 disponibles localement ; XChaCha20 est reproduit par la construction HChaCha20 + ChaCha20-Poly1305 IETF. Cette sonde n'est ni versionnée ni requise par KSP : elle sert uniquement de seconde implémentation de vérification.
Références cryptographiques normatives/primaires réauditées :
- RFC 9106 — Argon2 ; le profil Argon2id `64 MiB / t=3` est la seconde recommandation pour environnements contraints ;
- RFC 8032 — Ed25519/EdDSA et signatures 64 octets ;
- documentation RustCrypto `chacha20poly1305` — XChaCha20-Poly1305 et nonce étendu 192 bits ;
- documentation `solana-keypair 3.1.2` — keypair Ed25519 64 octets, validation secret/public et codecs Base58/JSON ;
- documentation `tempfile 3.27` — publication/replacement et limites d'atomicité selon OS/filesystem.
## 6. Audit Cargo observé après `pre.008`
Commande opérateur :
```bash
cargo tree -p ksp-wallet-lib
cargo tree -p ksp-wallet-lib -d
cargo tree -i solana-keypair@3.1.2
```
Dépendances directes de Wallet observées :
```text
argon2 0.5.3
base64 0.23.1
chacha20poly1305 0.11.0
ed25519-dalek 2.2.0
getrandom 0.4.3
ksp-core-lib
ksp-logging-lib
serde 1.0.229
serde_json 1.0.151
solana-keypair 3.1.2
tempfile 3.27.0
tokio 1.53.1
zeroize 1.9.0
```
Points de convergence recherchés :
```text
ed25519-dalek 2.2.0 : une seule génération, partagée KSP + solana-keypair
solana-address 2.7.0: une seule génération, partagée solana-pubkey + solana-keypair
solana-keypair 3.1.2: unique parent KSP direct = ksp-wallet-lib
```
Doublons transitifs observés et acceptés au gate :
```text
block-buffer 0.10 / 0.12
cpufeatures 0.2 / 0.3
crypto-common 0.1 / 0.2
digest 0.10 / 0.11
getrandom 0.3 / 0.4
rand 0.9 / 0.10
rand_core 0.6 / 0.9 / 0.10
sha2 0.10 / 0.11
syn 2 / 3
```
Ces doublons proviennent des générations transitives actuelles de RustCrypto, `solana-keypair`/`solana-ed25519` et Logging. Ils ne correspondent pas à deux versions directes déclarées par Wallet pour une même fonction. Les éliminer exigerait de forcer des upstream incompatibles ou de régresser les versions retenues ; aucun contournement KSP n'est introduit.
## 7. Frontières KSP
Canaries durables :
```text
Wallet -> Core + Logging + primitives explicites
Wallet -X-> Config
Wallet -X-> Transport
Wallet -X-> ExecutionPolicy
Wallet -X-> Store
Wallet -X-> Tauri
Wallet -X-> tracing direct
Wallet -X-> std::env
Wallet -X-> solana-pubkey direct
Wallet -X-> solana-signer direct
Wallet -X-> solana-signature direct
Wallet -X-> bs58 direct
```
`ksp-core-lib::Pubkey` reste le type public transversal. `solana-keypair` reste un détail secret/signing propre à Wallet ; aucune `Keypair`, `Signer` ou `Signature` Solana externe n'est réexportée par la surface publique Wallet.
`WalletTransferFormat` est `#[non_exhaustive]` : la liste built-in reste additive et les consumers ne peuvent pas supposer qu'elle est fermée. `pre.009` ne crée pas de trait/plugin externe de codec secret : un tel trait devrait exposer les 64 octets de keypair à une implémentation tierce et constituerait une nouvelle surface secrète. Cette extension éventuelle exige un contrat dédié futur plutôt qu'une abstraction V1 prématurée.
## 8. Limites et non-garanties V1
Le verdict security est positif **dans le threat model documenté**, avec les limites explicites suivantes :
1. un remplacement total par un autre wallet autonome valide n'est pas détectable à partir du nouveau fichier seul ;
2. un rollback total vers une ancienne copie valide n'est pas détecté sans état/ancre externe ;
3. le garde-fou `wallet.state_conflict` réduit les erreurs de cible/stale handle mais n'est pas un CAS filesystem portable linéarisable ;
4. l'atomicité et la crash-durability du filesystem dépendent de l'OS/filesystem ;
5. les ACL/permissions sont une hygiène externe, pas une garantie cryptographique ;
6. `zeroize` s'applique aux buffers possédés explicitement mais ne prouve pas l'effacement physique de toutes les copies potentielles ;
7. aucune protection hardware, second facteur, keychain, remote signer ou anti-rollback externe n'est incluse en V1.
Aucune de ces limites ne doit être masquée dans `pre.010`.
## 9. Gate opérateur `pre.009`
À exécuter après application du delta :
```bash
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-wallet-lib
cargo test --workspace
cargo tree -p ksp-wallet-lib
cargo tree -p ksp-wallet-lib -d
cargo tree -i ed25519-dalek@2.2.0
cargo tree -i solana-keypair@3.1.2
cargo tree -i solana-address@2.7.0
```
Le gate est vert seulement si les canaris adversariaux passent sans warning et si le tree ne révèle aucune nouvelle dépendance directe ou génération Dalek/Solana-address inattendue.
## 10. Verdict avant `pre.010`
Le verdict de conception et d'interopérabilité est **positif sous réserve du checkpoint Cargo opérateur `pre.009`**. Aucun changement de wire/crypto n'est requis par l'audit. `pre.010` doit donc rester documentaire : README/USAGE Wallet, synchronisation finale de la spec/graphes, candidate de clôture et prompt `0.2.6`.