v0.2.5-pre.005

This commit is contained in:
2026-08-19 13:09:16 +02:00
parent 3c069347b7
commit 36b98e0abc
27 changed files with 2305 additions and 113 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/000-README.md -->
<!-- version: 35 -->
<!-- version: 36 -->
# Documentation KSP
@@ -73,11 +73,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 gate `0.2.5-pre.001` est conservé dans [`plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md) : il réaudite bot2/bot3 et les crates actuelles, formalise le threat model offline, retient les capacités VIEW/OWNER indépendantes et le niveau B read-only, cadre le format interopérable `.kspwallet` V1 et redimensionne la release avant implémentation cryptographique.
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.
## 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), dont `0.2.5-pre.003` fige l'enveloppe JSON stricte, les key slots, les limites structurelles, le transcript OWNER et les AAD indépendamment de l'implémentation 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 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.
`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: 2 -->
<!-- version: 3 -->
# 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 son enveloppe JSON stricte, ses limites structurelles, ses key slots, son transcript OWNER et ses AAD ; `0.2.5-pre.004` ajoute Argon2id/XChaCha20-Poly1305/CSPRNG OS, le wrapping de content keys et le premier vecteur crypto déterministe. Le default Argon2 de création reste volontairement en attente du benchmark opérateur livré par cette tranche.
- [`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.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/formats/KSPWALLET_V1.md -->
<!-- version: 2 -->
<!-- version: 3 -->
# `.kspwallet` V1 — spécification du format natif Wallet KSP
@@ -20,7 +20,7 @@ AAD des compartiments owner-control / metadata / secret
règles unknown-field / unknown-version
```
`0.2.5-pre.004` complète maintenant les primitives KDF/AEAD normatives et un premier vecteur cryptographique public. Le **default de création Argon2id** reste volontairement non normatif tant que le benchmark opérateur de `pre.004` n'a pas été exécuté. Les prereleases suivantes complètent les payloads plaintext exacts, l'autorité Ed25519, les opérations create/open et les vecteurs de wallet complets. Toute évolution qui modifie un élément déjà déclaré **figé** par cette spécification exige une évolution explicitement tracée avant la release stable ; après publication de V1, une incompatibilité de wire exige un nouveau `format_version`.
`0.2.5-pre.004` ajoute les primitives KDF/AEAD normatives et un premier vecteur cryptographique public. `0.2.5-pre.005` fixe maintenant les payloads plaintext V1, l'autorité Ed25519 OWNER, les procédures de création et d'ouverture VIEW/OWNER, le profil de création KSP issu du benchmark opérateur et un vecteur `.kspwallet` complet généré indépendamment du code Rust. La persistence filesystem, les mutations administratives, la signature Solana publique et les adapters import/export restent dans les tranches suivantes. Toute évolution qui modifie un élément déjà déclaré **figé** par cette spécification exige une évolution explicitement tracée avant la release stable ; après publication de V1, une incompatibilité de wire exige un nouveau `format_version`.
Le but final est qu'une implémentation indépendante en Rust, Python, Go, C/C++, Java ou autre puisse créer, parser, vérifier et ouvrir un `.kspwallet` sans lire le code source de `ksp-wallet-lib`.
@@ -166,7 +166,7 @@ La forme V1 est :
}
```
Les valeurs Argon2 chiffrées dans cet exemple sont **des valeurs de fixture structurelle**, pas les defaults de création V1. Les defaults ne deviennent normatifs qu'après benchmark de `pre.004`.
Les valeurs Argon2 montrées dans l'exemple OWNER correspondent au profil de création KSP retenu en `pre.005`. L'exemple VIEW reste seulement illustratif : chaque key slot sérialise ses propres paramètres et toute combinaison respectant les bornes V1 reste lisible. Le profil par défaut KSP ne constitue donc pas une contrainte imposée aux implémentations externes conformes.
## 6. `owner_auth_public_key`
@@ -223,9 +223,20 @@ memory_kib >= 8 * parallelism
salt : 16 .. 64 octets
```
Ces plafonds sont des bornes de format/rejet hostile ; ils ne définissent pas les paramètres de **création par défaut**. Ceux-ci sont benchmarkés séparément.
Ces plafonds sont des bornes de format/rejet hostile ; ils ne définissent pas à eux seuls les paramètres de création.
Le password KDF futur est la séquence exacte des octets UTF-8 fournis, sans normalisation Unicode implicite, avec une longueur maximale de 1024 octets et un password vide refusé à la création.
Le profil de création KSP V1 retenu en `0.2.5-pre.005` est :
```text
memory_kib = 65 536
iterations = 3
parallelism = 1
salt = 32 octets CSPRNG neufs par slot
```
Le benchmark opérateur du 2026-08-19, exécuté avec le test calibrateur livré par `pre.004`, a mesuré environ 1742 ms pour `64 MiB / 3 / 1`, 3459 ms pour `128 MiB / 3 / 1` et 6925 ms pour `256 MiB / 3 / 1`. Le premier candidat est retenu comme équilibre initial ; ces mesures caractérisent la machine/profil testés et ne sont pas une promesse de latence portable. Les paramètres étant sérialisés dans chaque slot, KSP pourra durcir les defaults futurs sans rendre les wallets existants illisibles.
Le password KDF est la séquence exacte des octets UTF-8 fournis, sans normalisation Unicode implicite, avec une longueur maximale de 1024 octets et un password vide refusé.
### 8.2 Wrapping
@@ -240,7 +251,14 @@ ciphertext <= 4096 octets
Le ciphertext contient le tag Poly1305 de 16 octets produit par l'AEAD.
Le contenu plaintext exact des wrapped capabilities est figé avec la couche crypto/payload suivante ; la grammaire envelope/key-slot et son AAD sont déjà figés ici.
Le plaintext wrappé est exactement **32 octets** :
```text
OWNER slot -> K_owner_root (32 octets)
VIEW slot -> K_metadata (32 octets)
```
OWNER et VIEW ont des KDF/salts/nonces indépendants. OWNER n'a jamais besoin du slot VIEW pour accéder à `K_metadata`, puisque cette clé est également contenue dans `owner_control` sous `K_owner_root`.
## 9. Compartiments chiffrés
@@ -275,19 +293,57 @@ metadata : 16 .. 65 552 octets
secret : 16 .. 4096 octets
```
La metadata plaintext V1 reste bornée à 65 536 octets. Les payloads plaintext exacts sont consolidés dans la tranche dédiée, mais les champs wire ci-dessus ne changent pas.
La metadata plaintext V1 reste bornée à 65 536 octets. `pre.005` fixe les trois plaintexts :
Le compartiment metadata contient à terme au minimum :
### 9.1 `owner_control`
Plaintext binaire de **96 octets exacts**, dans cet ordre :
```text
Pubkey Solana Base58 canonique
alias optionnel <= 256 octets UTF-8
maximum 64 notes
texte note <= 8192 octets UTF-8
id de note = 16 octets aléatoires
offset 0..32 : admin_signing_secret Ed25519 (32 octets)
offset 32..64 : K_metadata (32 octets)
offset 64..96 : K_secret (32 octets)
```
Le compartiment secret contient la keypair Solana exacte nécessaire à la signature OWNER.
`admin_signing_secret` est la seed privée Ed25519 correspondant à `owner_auth_public_key`. Cette autorité est distincte de la keypair Solana.
### 9.2 `metadata`
Plaintext JSON UTF-8, objet strict sans champs inconnus :
```json
{
"pubkey": "<Pubkey Solana Base58 canonique>",
"alias": "<string ou null>",
"notes": [
{"id": "<16 octets Base64url sans padding>", "text": "<UTF-8>"}
]
}
```
Contraintes :
```text
pubkey = Base58 canonique d'une Pubkey Solana 32 octets
alias = null ou <= 256 octets UTF-8
notes = maximum 64
note.id = exactement 16 octets, Base64url canonique sans padding, unique dans le payload
note.text = <= 8192 octets UTF-8
payload total <= 65 536 octets
```
L'ordre des propriétés JSON du plaintext metadata n'est pas cryptographiquement canonicalisé : l'AEAD protège les octets plaintext réellement choisis par le créateur, et la signature OWNER protège ensuite le ciphertext. Le serializer KSP émet un JSON compact dans l'ordre `pubkey`, `alias`, `notes`, puis `id`, `text` pour chaque note.
### 9.3 `secret`
Plaintext binaire de **64 octets exacts**, compatible avec la représentation Solana/Ed25519 standard :
```text
offset 0..32 : secret Ed25519 Solana
offset 32..64 : public Ed25519 Solana
```
À l'ouverture OWNER, l'implémentation doit valider que la moitié publique correspond au secret et que la Pubkey dérivée est exactement celle du payload metadata. Un mismatch est du key material invalide, jamais une nouvelle identité acceptée silencieusement.
## 10. Signature d'état OWNER
@@ -304,6 +360,8 @@ La signature porte sur le **transcript sémantique OWNER-controlled**, jamais su
Les paramètres/salt/nonce/ciphertext du slot VIEW self-service sont exclus de la signature OWNER ; le descripteur stable VIEW est inclus.
La vérification Ed25519 de l'état OWNER-controlled doit précéder toute dérivation de password. `owner_auth_public_key` est parsée comme clé de vérification Ed25519 et la signature est vérifiée en mode strict sur le transcript exact de la section 12. Une mutation de metadata/secret/owner-control/slot OWNER sans clé privée d'administration est donc rejetée avant Argon2. Lors d'une ouverture OWNER, la seed d'administration déchiffrée depuis `owner_control` doit en plus redériver exactement `owner_auth_public_key`.
## 11. Codec binaire transcript/AAD
### 11.1 Préfixe de domaine
@@ -603,19 +661,20 @@ AAD exacts
round-trip du codec
```
Le premier vecteur cryptographique public KDF+wrapping est ajouté par `pre.004`. Les vecteurs de wallet complets incluant payloads et state signature sont ajoutés après implémentation des compartiments et de l'autorité OWNER.
Le premier vecteur cryptographique public KDF+wrapping est ajouté par `pre.004`. `pre.005` ajoute en plus un `.kspwallet` complet cryptographiquement valide et ses métadonnées de contrôle test-only, décrits en section 22.
## 19. Invariants encore à compléter sans modifier le wire figé
Les tranches suivantes doivent compléter :
Après `pre.005`, les tranches restantes portent sur les opérations autour du format déjà défini :
```text
pre.004 : sélection finale du default Argon2 après benchmark opérateur (KDF/AEAD/wrapping/vecteur déjà implémentés)
pre.005 : payloads owner-control/metadata/secret + create/open VIEW/OWNER + state signature effective
pre.006+ : persistence/administration/signature/import-export selon le plan Wallet
pre.006 : persistence async/atomique/no-clobber
pre.007 : signature Solana, metadata admin, rotations OWNER/VIEW et révocation forte VIEW
pre.008 : import/export
pre.009+ : audit adversarial, compliance et documentation de clôture
```
Toute découverte imposant de modifier la grammaire, les tags, l'ordre transcript ou les domain separators définis dans ce document doit être traitée explicitement avant la publication stable, jamais masquée par une tolérance du parseur.
Toute découverte imposant de modifier la grammaire, les payloads plaintext, les tags, l'ordre transcript ou les domain separators définis dans ce document doit être traitée explicitement avant la publication stable, jamais masquée par une tolérance du parseur.
## 20. Primitives cryptographiques effectives depuis `pre.004`
@@ -638,15 +697,15 @@ secret Argon2 externe = aucun
Un password vide est rejeté. V1 limite l'entrée password à 1024 octets UTF-8. Le KDF est une opération CPU/mémoire coûteuse ; les futures API async create/open l'exécuteront hors du thread executor conformément au plan Wallet.
Le default de création n'est **pas** déterminé par les defaults de la crate RustCrypto. Le benchmark opérateur compare explicitement :
Le default de création n'est **pas** déterminé par les defaults de la crate RustCrypto. Le benchmark opérateur a comparé :
```text
64 MiB / 3 passes / 1 lane
128 MiB / 3 passes / 1 lane
256 MiB / 3 passes / 1 lane
64 MiB / 3 passes / 1 lane -> 1742 ms
128 MiB / 3 passes / 1 lane -> 3459 ms
256 MiB / 3 passes / 1 lane -> 6925 ms
```
Le profil retenu sera enregistré après mesure sur machine cible. Un wallet conserve toujours ses propres paramètres sérialisés, indépendamment des defaults futurs.
KSP retient donc initialement `64 MiB / 3 / 1` avec un salt CSPRNG de 32 octets par slot. Un wallet conserve toujours ses propres paramètres sérialisés, indépendamment des defaults futurs.
### 20.2 XChaCha20-Poly1305
@@ -685,3 +744,89 @@ XChaCha20-Poly1305(derived_key, nonce, AAD, content_key) -> wrapped_key attendu
```
Le vecteur a été recalculé indépendamment de l'implémentation Rust avec Argon2id puis la construction XChaCha20-Poly1305 `HChaCha20 + ChaCha20-Poly1305 IETF`. Ces valeurs ne constituent jamais des secrets de production.
## 21. Procédures V1 matérialisées par `pre.005`
### 21.1 Création
Une création KSP V1 en mémoire suit conceptuellement :
```text
1. générer K_owner_root, K_metadata et K_secret indépendants (32 octets chacun) ;
2. générer une seed Ed25519 d'administration de format indépendante de la keypair Solana ;
3. générer une nouvelle keypair Solana Ed25519 et dériver la Pubkey metadata ;
4. encoder owner_control, metadata et secret selon la section 9 ;
5. générer slot_id/salt/nonce OWNER et, si demandé, slot_id/salt/nonce VIEW indépendants ;
6. Argon2id(password OWNER) -> KEK_OWNER -> wrap K_owner_root ;
7. si VIEW existe : Argon2id(password VIEW) -> KEK_VIEW -> wrap K_metadata ;
8. chiffrer owner_control avec K_owner_root, metadata avec K_metadata, secret avec K_secret ;
9. construire le transcript OWNER et le signer avec l'autorité Ed25519 de format ;
10. vérifier immédiatement la signature produite avant de retourner le handle OWNER.
```
Les opérations Argon2id sont exécutées hors du thread executor async par une frontière blocking dédiée. La création `pre.005` est **in-memory** : la persistence arrive en `pre.006`.
### 21.2 Ouverture VIEW
```text
1. parser/rejeter strictement l'enveloppe ;
2. vérifier la state signature OWNER avant tout KDF ;
3. exiger un slot VIEW cohérent avec view_descriptor ;
4. Argon2id(password VIEW, paramètres du slot VIEW) ;
5. unwrap K_metadata avec l'AAD VIEW courant ;
6. déchiffrer uniquement metadata ;
7. valider le payload metadata ;
8. retourner Pubkey/alias/notes + capability VIEW.
```
Une ouverture VIEW ne déchiffre **jamais** `owner_control` ni `secret` et ne matérialise ni `K_owner_root`, ni `K_secret`, ni la keypair Solana, ni la seed Ed25519 d'administration.
### 21.3 Ouverture OWNER
```text
1. parser/rejeter strictement l'enveloppe ;
2. vérifier la state signature OWNER avant tout KDF ;
3. Argon2id(password OWNER, paramètres slot OWNER) ;
4. unwrap K_owner_root ;
5. déchiffrer owner_control et récupérer admin_signing_secret, K_metadata, K_secret ;
6. vérifier que admin_signing_secret redérive owner_auth_public_key ;
7. déchiffrer/valider metadata ;
8. déchiffrer secret, reconstruire strictement la keypair Solana 64 octets ;
9. vérifier cohérence secret/public et égalité avec la Pubkey metadata ;
10. retourner capability OWNER en conservant les secrets seulement dans l'état OWNER opaque.
```
Aucun getter public de secret n'est introduit par cette procédure.
## 22. Vecteur complet interopérable `pre.005`
Le dépôt publie :
```text
crates/ksp-wallet-lib/tests/fixtures/kspwallet_v1_full_vector.json
crates/ksp-wallet-lib/tests/fixtures/kspwallet_v1_full_vector_meta.json
```
Ces fichiers sont **TEST ONLY**. Ils publient volontairement passwords, secrets, clés et résultats attendus et ne doivent jamais servir de wallet réel ni d'exemple de paramètres sécurisés. Pour garder les tests rapides, leurs key slots utilisent `32 KiB / 2 / 1`, très en dessous du profil de création KSP.
Le vector fixe notamment :
```text
password OWNER = pre005-owner-password
password VIEW = pre005-view-password
Pubkey attendue = 8zH45w576QJUEGtpXqZvEi6UPddmMfKopLatocZGDw6
alias attendu = pre005-vector-wallet
2 notes test-only
owner/view derived keys
autorité Ed25519
K_owner_root / K_metadata / K_secret
owner-control plaintext
metadata plaintext
keypair Solana 64 octets
state transcript exact
state signature exacte
wallet JSON complet
```
Le vecteur a été généré et revérifié indépendamment du code Rust avec Argon2id, XChaCha20-Poly1305 construit via HChaCha20 + ChaCha20-Poly1305 IETF et Ed25519. Une implémentation externe conforme doit pouvoir reproduire les mêmes dérivations, déchiffrements et vérifications à partir des deux fichiers sans dépendre d'un type Rust KSP.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/000-README.md -->
<!-- version: 42 -->
<!-- version: 43 -->
# Plans KSP
@@ -20,7 +20,7 @@ Un plan décrit le périmètre, les décisions déjà acquises, les questions ou
- [`009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md`](009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md) — plan clôturé de la release stable `0.2.2`, établi par `pre.001`, corrigé après réaudit Agave v4.2.1 puis exécuté jusqu'à `pre.007-fix.002`; il couvre les 22 wrappers Accounts/Tokens/Cluster, le smoke Transport opt-in et la préparation de `0.2.3`.
- [`010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md`](010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md) — plan historique clôturé de la release stable `0.2.3 — HTTP Transactions`, ouvert par `pre.001`, exécuté jusqu'à `pre.009` puis publié par `rel.001`; il couvre les 11 méthodes, la classification `8 Read / 2 WriteSubmission / 1 Simulation`, `KSP-TRANSPORT-007`, le no-resend et la préparation de `0.2.4`.
- [`011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md`](011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md) — plan historique clôturé de la release stable `0.2.4`, ouvert par `pre.001`, exécuté jusquà `pre.009`, complété par le fix documentaire Wallet `pre.009-fix.001` puis publié par `rel.001`; il couvre les 10 Blocks + 5 Economics et la compliance finale `52/52 + 14/14` sous `KSP-TRANSPORT-007`.
- [`012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](012-V0_2_5_WALLET_FOUNDATION_PLAN.md) — plan actif de `0.2.5 — Wallet foundation`, ouvert par `pre.001`; `pre.002` matérialise la crate et `pre.003` fige le wire JSON V1, ses key slots, limites, transcript/AAD et la première spécification interopérable `docs/formats/KSPWALLET_V1.md`, avant la cryptographie effective de `pre.004+`.
- [`012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](012-V0_2_5_WALLET_FOUNDATION_PLAN.md) — plan actif de `0.2.5 — Wallet foundation`, ouvert par `pre.001`; `pre.002` matérialise la crate, `pre.003` fige le wire JSON V1/transcript/AAD, `pre.004` ajoute Argon2id/XChaCha20-Poly1305/CSPRNG et `pre.005` fixe les payloads, le profil de création benchmarké, lautorité Ed25519 séparée et les flux in-memory create/open VIEW/OWNER avec vecteur complet interopérable. `pre.006` porte la persistence atomique/no-clobber.
Le `pre.001` de chaque release fonctionnelle peut introduire son propre plan détaillé lorsque la release s'ouvre.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md -->
<!-- version: 49 -->
<!-- version: 50 -->
# Séquence des releases fonctionnelles KSP
@@ -414,6 +414,8 @@ La release doit fournir `docs/formats/KSPWALLET_V1.md` comme spécification sép
`0.2.5-pre.004` matérialise les primitives cryptographiques in-memory sans encore créer/ouvrir un wallet complet : Argon2id version 19 dérive une KEK de 32 octets depuis le password et les paramètres sérialisés, XChaCha20-Poly1305 wrappe/déwrappe les content keys avec les AAD figés, `getrandom` fournit le CSPRNG OS et les buffers secrets possédés sont zeroized. Un vecteur public test-only fixe l'interop KDF+AEAD. Le profil Argon2 de création n'est pas inventé : trois candidats sont benchmarkables par un test `#[ignore]` et le gate `pre.005` attend le résultat opérateur avant de figer le default.
`0.2.5-pre.005` consomme ce benchmark (`64 MiB / 3 / 1 ≈ 1742 ms`, `128 MiB ≈ 3459 ms`, `256 MiB ≈ 6925 ms` sur la machine opérateur) et retient pour les créations KSP V1 `65 536 KiB / 3 / 1` avec salt 32 octets, tout en conservant les paramètres sérialisés comme autorité de lecture de chaque wallet. La tranche fixe les payloads `owner_control` (seed Ed25519 dadministration + `K_metadata` + `K_secret`), metadata strictes et secret Solana 64 octets, ajoute une autorité Ed25519 séparée de la keypair Solana et vérifie sa signature détat avant tout KDF. Les API in-memory `create_wallet_v1`, `open_wallet_view_v1`, `open_wallet_owner_v1` et `inspect_locked_wallet_v1` matérialisent lindépendance VIEW/OWNER : VIEW ne déchiffre jamais `owner_control`/secret, OWNER ne dépend pas de VIEW et la Pubkey reste un `ksp_core_lib::Pubkey`. Un vecteur `.kspwallet` complet test-only, revérifiable hors Rust, ferme linterop de cette tranche. La persistence filesystem reste explicitement `pre.006`; signature Solana publique et mutations/rotations restent `pre.007+`.
## `0.2.6` — Wallet Desk
Mission : valider Config composite + `.kspwallet` + transport HTTP dans une application Tauri mince.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md -->
<!-- version: 7 -->
<!-- version: 8 -->
# Plan `0.2.5` — Wallet foundation
@@ -363,7 +363,7 @@ Il faut distinguer :
**keypair Solana** : immuable dans V1 après création/import. Aucun `replace_keypair` n'est exposé. Toute tentative de modifier `secret` ou la Pubkey metadata sans une réécriture OWNER valide échoue sur la `state_signature`; même avec OWNER, l'import d'une autre keypair crée un nouveau `.kspwallet` au lieu de muter l'identité cryptographique existante.
## 8. Primitives et dépendances réauditées le 2026-08-18
## 8. Primitives et dépendances réauditées jusquau 2026-08-19
Aucune dépendance ci-dessous n'est ajoutée dans `pre.001`. Ce sont les candidates pour les tranches qui les consommeront réellement.
@@ -378,9 +378,9 @@ Aucune dépendance ci-dessous n'est ajoutée dans `pre.001`. Ce sont les candida
`solana-keypair` fournit le keypair Ed25519, la conversion stricte depuis 64 octets, la signature, le format JSON de 64 entiers et une représentation Base58 complète. Aucun client RPC Solana n'est nécessaire.
La génération SDK récente définit `Pubkey` comme alias du type `Address`, mais l'écosystème a déjà connu des incompatibilités lorsque plusieurs générations de `solana-address` coexistent. `pre.002` verrouille donc la surface publique Wallet sur **`ksp_core_lib::Pubkey` exclusivement** et n'ajoute aucune dépendance directe `solana-pubkey`. Lorsque `solana-keypair` sera réellement introduit, la tranche concernée devra prouver par compilation/cargo-tree que son `Address/Pubkey` est compatible avec la génération possédée par Core avant toute conversion interne. Aucun second type d'adresse KSP n'est introduit pour contourner un mismatch.
La génération SDK récente définit `Pubkey` comme alias du type `Address`, mais l'écosystème a déjà connu des incompatibilités lorsque plusieurs générations de `solana-address` coexistent. `pre.002` verrouille donc la surface publique Wallet sur **`ksp_core_lib::Pubkey` exclusivement** et n'ajoute aucune dépendance directe `solana-pubkey`. `pre.005` introduit réellement `solana-keypair 3.1.2` uniquement pour posséder/valider la keypair Ed25519 ; la Pubkey Wallet reste construite via `ksp_core_lib::Pubkey` depuis les 32 octets publics du keypair, sans exposer un second type d'adresse KSP.
Un `cargo tree` est obligatoire lors de l'introduction réelle afin de contrôler les versions `ed25519-dalek`, `solana-signature`, `rand/getrandom` et éviter des duplications évitables.
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.
@@ -392,9 +392,9 @@ Audit source notable : `solana-keypair 3.1.2` contient un bloc `unsafe` interne
| scrypt | `0.12.0` | alternative maintenue, non ajoutée |
| PBKDF2 | `0.13.0` | compatibilité/legacy seulement, non ajouté |
Les paramètres Argon2 de création sont benchmarkés sur les machines cibles. `pre.004` livre trois candidats explicites (64 MiB / 128 MiB / 256 MiB, trois passes, une lane) et un test opérateur ignoré par défaut ; **aucun candidat n'est déclaré default avant retour du benchmark opérateur**. Ils ne sont pas copiés de bot3, d'un RFC ou d'un default de crate. Le fichier sérialise tous les paramètres nécessaires afin qu'un ancien wallet conserve son profil historique.
Les paramètres Argon2 de création ont été mesurés avec le benchmark opérateur de `pre.004` : `64 MiB / 3 / 1 = 1742 ms`, `128 MiB / 3 / 1 = 3459 ms`, `256 MiB / 3 / 1 = 6925 ms` sur la machine/profil testés le 2026-08-19. `pre.005` retient donc **64 MiB / 3 passes / 1 lane** comme profil initial de création KSP, avec un salt CSPRNG indépendant de 32 octets par slot. Ce choix n'est copié ni de bot3, ni d'un RFC, ni d'un default de crate. Le fichier sérialise tous les paramètres nécessaires afin qu'un ancien wallet conserve son profil historique même lorsque les defaults KSP seront durcis.
Le parseur impose des **bornes maximales** avant de lancer le KDF, afin qu'un fichier hostile ne puisse demander arbitrairement mémoire/CPU. `pre.004` ajoute également l'invariant Argon2 `memory_kib >= 8 * parallelism` avant tout calcul coûteux. Les bornes structurelles restent indépendantes du default de création ; celui-ci est figé seulement après le benchmark opérateur de `pre.004`.
Le parseur impose des **bornes maximales** avant de lancer le KDF, afin qu'un fichier hostile ne puisse demander arbitrairement mémoire/CPU. `pre.004` ajoute également l'invariant Argon2 `memory_kib >= 8 * parallelism` avant tout calcul coûteux. Les bornes structurelles restent indépendantes du profil de création KSP.
### 8.3 AEAD
@@ -409,13 +409,13 @@ AES-GCM-SIV apporte une meilleure tolérance à la réutilisation accidentelle d
### 8.4 CSPRNG
`getrandom 0.4.3` est retenu comme candidate low-level pour les octets aléatoires propres au format. Les API de génération de keypair Solana restent libres d'utiliser leur CSPRNG interne maintenu.
`getrandom 0.4.3` est retenu depuis `pre.004` comme primitive low-level pour les octets aléatoires propres au format. `pre.005` l'utilise également pour les seeds/slot IDs/salts/nonces de création. Les API de génération de keypair Solana ne deviennent pas pour autant propriétaires du CSPRNG du format.
### 8.5 Secret memory
`zeroize 1.9.0` est retenu et devient la seule nouvelle dépendance tierce de `pre.002`, car les wrappers `ViewPassword` / `OwnerPassword` lutilisent immédiatement pour leur nettoyage au `Drop`. `secrecy` n'est pas ajouté tant qu'un besoin ergonomique concret n'est pas démontré ; des types KSP simples imposent eux-mêmes redaction/non-Clone et utilisent `zeroize`.
Pour la clé admin Ed25519 distincte, `ed25519-dalek 3.0.0` est une candidate standard, mais son ajout direct est **conditionné au cargo-tree** de la tranche qui implémente l'authentification afin d'éviter une génération concurrente inutile avec celle déjà tirée par `solana-keypair`.
`pre.005` introduit directement **`ed25519-dalek ^2.2`** avec `default-features = false` et les features `signature` + `zeroize`. La génération `3.0.0`, bien que plus récente, n'est volontairement pas ajoutée : `solana-keypair 3.1.2` dépend de `ed25519-dalek ^2.1.1`, donc la branche directe `2.2` permet à Cargo d'unifier une seule génération Dalek et d'activer `zeroize` sur la `SigningKey` utilisée à la fois par l'autorité de format KSP et par le wrapper Solana. Une duplication `2.x + 3.x` n'apporterait aucune capacité nécessaire à V1.
### 8.6 État des audits de sécurité publics
@@ -432,14 +432,14 @@ L'absence d'une ligne « audited » dans ce document ne signifie donc pas « sû
### 8.7 Encodage et persistence
Candidates :
État au terme de `pre.005` :
```text
base64 0.23.1 pour Base64url sans padding des champs binaires JSON
tempfile 3.27.0 pour temp files same-directory + persist/persist_noclobber
base64 0.23.1 acquis depuis pre.003 pour Base64url sans padding des champs binaires JSON
tempfile 3.27.0 candidate pre.006 pour temp files same-directory + persist/persist_noclobber
```
Elles ne sont ajoutées que lorsqu'elles sont réellement consommées.
`tempfile` ne sera ajouté que si `pre.006` confirme sa sémantique portable et son besoin réel pour l'atomicité/no-clobber.
## 9. Format natif `.kspwallet` V1
@@ -516,7 +516,7 @@ Structure V1 figée par le codec `pre.003` (les longueurs/encodages exacts sont
}
```
Les `0` ci-dessus signifient « valeur déterminée par le benchmark futur », pas des paramètres valides.
Les paramètres de création KSP V1 sont désormais `memory_kib = 65536`, `iterations = 3`, `parallelism = 1`, avec un salt CSPRNG indépendant de 32 octets par slot. Le wire continue toutefois d'accepter tout profil V1 valide dans les bornes documentées, car les paramètres sont sérialisés par wallet.
### 9.3 Informations visibles wallet verrouillé
@@ -1031,6 +1031,26 @@ L'injection de random déterministe reste privée aux tests/codec fixtures ; l'A
- aucun `unsafe` KSP ;
- cargo-tree sans duplication crypto injustifiée.
### 19.7 État acquis après `pre.005`
`pre.005` matérialise désormais les invariants crypto centraux sans filesystem :
```text
K_owner_root, K_metadata, K_secret indépendants
OWNER slot -> K_owner_root
VIEW slot -> K_metadata
owner_control = admin Ed25519 secret || K_metadata || K_secret (96 octets)
metadata = JSON protégé Pubkey/alias/notes avec note IDs 16 octets uniques
secret = keypair Solana 64 octets secret||public
state_signature Ed25519 vérifiée avant tout KDF
open VIEW ne matérialise jamais owner-control/secret
open OWNER vérifie autorité admin + cohérence keypair + Pubkey metadata
create/open KDF via spawn_blocking
vecteur complet test-only généré et revérifié indépendamment du Rust
```
La persistence, la signature Solana publique, les mutations metadata et les rotations restent volontairement absentes de cette tranche.
## 20. Sizing
| Domaine | Taille | Risque principal |
@@ -1070,31 +1090,32 @@ rel.001 publication strictement publicationnelle
Une `fix` ou tranche supplémentaire est préférable à la suppression d'une garantie sécurité si un des gates révèle une incompatibilité.
## 22. Dépendances candidates par tranche
## 22. Dépendances par tranche
`pre.001` najoutait aucune dépendance. `pre.002` ajoute uniquement :
État réellement acquis au terme de `pre.005` :
```text
zeroize ^1.9
pre.002 zeroize ^1.9
pre.003 base64 ^0.23
pre.004 argon2 ^0.5
chacha20poly1305 ^0.11
getrandom ^0.4
pre.005 ed25519-dalek ^2.2
solana-keypair ^3.1
tokio déjà workspace, feature locale rt pour spawn_blocking
```
La dépendance est centralisée sous `[workspace.dependencies]` puis consommée avec `zeroize.workspace = true`. Elle est utilisée immédiatement par les wrappers de password ; aucune crate crypto/KDF/Solana supplémentaire nest ajoutée par anticipation. La génération courante `zeroize 1.9.0` a été réauditée avant insertion.
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.
Liste de travail restante, à réauditer juste avant insertion sous `[workspace.dependencies]` :
Candidates restantes, à réauditer juste avant insertion :
```text
argon2 ^0.5
base64 ^0.23
chacha20poly1305 ^0.11
ed25519-dalek ^3.0 # seulement si cargo-tree justifie le direct
getrandom ^0.4
solana-keypair ^3.1
solana-signer ^3.0 # si réellement nécessaire directement
tempfile ^3.27 # pre.006 si la sémantique atomic/no-clobber est confirmée
solana-signer ^3.0 # seulement si un contrat public/impl l'exige réellement
solana-signature ^3.5 # seulement si le type public l'exige
tempfile ^3.27
```
Déjà présents et réutilisables :
Déjà présents et réutilisés :
```text
serde
@@ -1122,7 +1143,7 @@ Le fait que `bs58` ne soit pas requis sera révalidé lorsque les adapters sont
## 23. Sources externes réauditées
Sources primaires consultées le 2026-08-18 :
Sources primaires consultées initialement le 2026-08-18 puis réauditées le 2026-08-19 pour les dépendances effectivement introduites par `pre.005` :
```text
https://docs.rs/solana-keypair/3.1.2/
@@ -1136,12 +1157,12 @@ https://docs.rs/chacha20poly1305/0.11.0/
https://docs.rs/aes-gcm-siv/0.12.0/
https://docs.rs/getrandom/0.4.3/
https://docs.rs/zeroize/1.9.0/
https://docs.rs/ed25519-dalek/3.0.0/
https://docs.rs/ed25519-dalek/2.2.0/
https://docs.rs/base64/0.23.1/
https://docs.rs/tempfile/3.27.0/
```
Les versions sont des constats d'audit du gate, pas des dépendances ajoutées par ce delta. Chaque tranche réaudite sa candidate au moment où elle devient réellement consommée.
Les versions sont des constats d'audit successifs : elles ne signifient pas que toutes les crates listées ont été ajoutées dans une même tranche. Chaque dépendance sensible est réauditée au moment où elle devient réellement consommée.
## 24. Critères de sortie `0.2.5`
@@ -1197,4 +1218,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`. `0.2.5-pre.004` ajoute les primitives effectives Argon2id v19, XChaCha20-Poly1305, CSPRNG OS, wrapping de content keys, zeroization des clés possédées et un vecteur crypto public déterministe. La seule partie de `pre.004` qui reste volontairement à confirmer par lopérateur est le choix du **default de création Argon2**, via le benchmark candidat livré et ignoré par défaut. `pre.005` ne doit pas figer ce default sans ce résultat.
`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 a ensuite permis à `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, de créer/ouvrir réellement VIEW et OWNER en mémoire et de publier un vecteur `.kspwallet` complet interopérable. **La suite immédiate est `pre.006` : persistence async/atomique/no-clobber**, sans déplacer de logique filesystem dans Config.