11 KiB
Delta 0.2.6-pre.016 — runtime .kspwallet V2, APIs multi-version et Wallet Desk version-neutral
Base requise
0.2.6-pre.015-fix.001 appliquée
workspace.package.version = 0.2.6-pre.15.fix.1
Le checkpoint opérateur de cette base est intégralement vert :
cargo fmt --all OK
python3 scripts/audit_rust_workspace_rules.py clean
cargo check --workspace OK
cargo clippy --workspace --all-targets OK
cargo test --workspace OK
ksp-wallet-lib 71 passed / 1 ignored
Wallet Desk release_compliance 4/4 OK
smokes réseau / benchmark ignored comme prévu
Le correctif pre.015-fix.001 est donc accepté comme base de pre.016.
Signal technique
Cette tranche modifie les APIs/runtime Wallet et le backend Wallet Desk :
workspace.package.version = 0.2.6-pre.16
commit = v0.2.6-pre.016
Aucun tag prerelease.
Les package.json/tauri.conf.json ne sont pas modifiés : aucune dépendance frontend, configuration Tauri, permission ou contrat de bundle n'est changé. Le signal technique Rust reste porté par workspace.package.version.
Objectif de la tranche
pre.016 matérialise le contrat décidé en pre.015 : V2 devient le format natif default explicite des créations/imports non versionnés, sans rendre le default dépendant de la dernière version supportée.
La tranche ajoute simultanément :
runtime cryptographique V2 create/open VIEW/OWNER
persistence V2 create no-clobber + remplacement atomique
state-conflict V2 authentifié
façade in-memory multi-version
façade filesystem multi-version
variantes explicites V1/V2
import transfer default V2 + variantes V1/V2
handles OWNER/VIEW version-neutral
administration V2 complète
Wallet Desk exclusivement sur APIs génériques
canaris default/latest, V1/V2 et strict version dispatch
La migration persistée V1 -> V2 reste volontairement hors scope et appartient à pre.017.
Politique durable : default distinct de latest
La politique est désormais matérialisée dans ksp-wallet-lib :
DEFAULT_WALLET_FORMAT = WalletFormat::V2
LATEST_SUPPORTED_WALLET_FORMAT = WalletFormat::V2
WalletFormat est public et non_exhaustive afin qu'un futur V3 puisse être ajouté sans inviter les consumers à supposer que V2 est la dernière version possible.
Invariant durable :
DEFAULT_WALLET_FORMAT != conceptuellement LATEST_SUPPORTED_WALLET_FORMAT
Les deux valeurs sont V2 dans cette release, mais leur égalité est contingente. Si V3 apparaît plus tard :
DEFAULT_WALLET_FORMAT peut rester V2
LATEST_SUPPORTED_WALLET_FORMAT peut devenir V3
Une nouvelle version supportée ne change jamais automatiquement le default.
APIs de création
In-memory
create_wallet(...) -> DEFAULT_WALLET_FORMAT, donc V2
create_wallet_v1(...) -> V1 forcé
create_wallet_v2(...) -> V2 forcé
Filesystem
create_wallet_file(...) -> DEFAULT_WALLET_FORMAT, donc V2
create_wallet_file_v1(...) -> V1 forcé
create_wallet_file_v2(...) -> V2 forcé
Le type version-neutral WalletCreateMetadata est exposé pour les nouvelles APIs ; WalletCreateMetadataV1 reste conservé pour compatibilité explicite V1. Le profil plaintext initial de metadata V2 conserve la sémantique établie en V1, conformément à la spec V2.
APIs de lecture et inspection
Les APIs génériques détectent uniquement le framing nécessaire à la sélection du parser :
open_wallet_view(...)
open_wallet_owner(...)
inspect_locked_wallet(...)
open_wallet_view_file(...)
open_wallet_owner_file(...)
inspect_locked_wallet_file(...)
Dispatch :
JSON dont le premier octet significatif est '{' -> parser strict V1
magic binaire KSPWALLET + version 2 -> parser strict V2
autre framing/version -> erreur format/version
La détection n'est jamais une validation de substitution : le parser V1/V2 sélectionné reste autoritatif pour toutes les contraintes structurelles et cryptographiques.
Les APIs explicitement versionnées restent strictes :
*_v1 refuse V2
*_v2 refuse V1
Runtime V2
wallet_v2.rs compose le wire/transcript figé en pre.015 avec les primitives Wallet existantes :
Argon2id password KDF
XChaCha20-Poly1305 key wrapping
XChaCha20-Poly1305 OWNER-CONTROL / METADATA / SECRET
Ed25519 OWNER state signature
VIEW / OWNER indépendants
Solana keypair secret compartment
V2 conserve le profil plaintext fonctionnel initial de V1 pour owner-control, metadata et secret, mais utilise exclusivement :
wire V2
IDs V2
AAD V2
state transcript V2
format_version = 2
Les domains V1/V2 restent non interchangeables.
Handles OWNER / VIEW version-neutral
WalletOwner et WalletView ne sont plus couplés à OwnerStateV1 / ViewStateV1.
Un dispatch runtime interne conserve le format authentifié :
OwnerState::V1 / OwnerState::V2
ViewState::V1 / ViewState::V2
Les opérations publiques restent stables et dispatchent dans le format du handle :
signature OWNER
metadata alias/notes
rotation OWNER
rotation VIEW par OWNER
VIEW self-rotation
disable VIEW fort
recreate VIEW fort
export transfer
Une mutation V1 reste V1. Une mutation V2 reste V2.
Aucune de ces opérations ne constitue une migration.
Sérialisation des handles
Nouvelle surface :
to_native_bytes() -> V1 JSON si handle V1, V2 binaire si handle V2
Compatibilité historique :
to_json_bytes() -> fonctionne uniquement pour V1
rejette V2
Il n'existe aucune transcodification implicite V2 -> V1 ou V1 -> V2.
Persistence V2 et stale-handle protection
La création V2 conserve les garanties V1 :
construction complète en mémoire
écriture temporaire
sync
publication no-clobber
aucun overwrite d'une destination existante
Les mutations V2 réutilisent la discipline atomique avec une vérification format-spécifique :
relire destination bornée
parse_binary V2 strict
vérifier state signature V2
comparer l'enveloppe authentifiée attendue
publier seulement si état courant identique
Un handle V2 stale reçoit le même contrat wallet.state_conflict qu'un handle V1.
Import transfer
Les formats de transfert externes restent indépendants du format natif .kspwallet :
Solana CLI JSON
Solana keypair Base58 complet
La sortie native suit désormais :
import_wallet_transfer(...) -> V2 default
import_wallet_transfer_v1(...) -> V1 forcé
import_wallet_transfer_v2(...) -> V2 forcé
import_wallet_transfer_file(...) -> V2 default
import_wallet_transfer_file_v1(...) -> V1 forcé
import_wallet_transfer_file_v2(...) -> V2 forcé
La keypair Solana reste identique ; seul le nouvel environnement natif KSP est créé dans la version choisie.
Wallet Desk
ksp-app-wallet-desk ne référence plus aucune API native versionnée en production.
Ses callsites utilisent uniquement :
create_wallet_file
import_wallet_transfer
open_wallet_view_file
open_wallet_owner_file
inspect_locked_wallet_file
Conséquences :
nouveau Wallet créé depuis le Desk V2
nouvel import depuis le Desk V2
wallet V1 existant toujours inspectable/ouvrable
wallet V2 inspectable/ouvrable
mutations après unlock format natif conservé
frontend ne connaît pas V1/V2 pour dispatcher
La version reste visible dans les projections métier (format_version) mais n'est pas une responsabilité de routing du frontend/Tauri.
Canaris pre.016
Les nouveaux tests couvrent notamment :
DEFAULT_WALLET_FORMAT = V2
LATEST_SUPPORTED_WALLET_FORMAT = V2
framing detector V1/V2
création V2 + open générique VIEW/OWNER
lecture générique d'une fixture V1 stable
création fichier générique -> V2
metadata V2 persistée
rotation OWNER V2
rotation VIEW V2 par OWNER
disable/recreate VIEW V2
VIEW self-rotation V2
wire V2 conservé après administration
lecteur V1 forcé refuse V2
lecteur V2 forcé refuse V1
import transfer générique -> V2
import transfer V1 explicite toujours disponible
Wallet Desk sans callsite *_v1/*_v2
Les anciens canaris Desk pre.006/pre.009 sont réalignés sur la façade générique sans supprimer leurs garanties de sécurité historiques.
Hors scope
pre.016 ne réalise pas :
migration V1 -> V2
réécriture automatique à l'ouverture
suppression des APIs V1
V3 / second facteur
changement de default futur automatique
frontend spécifique au format
nouvelle permission Tauri
build Tauri de production
Documentation synchronisée
Cette tranche met à jour :
ROADMAP.md
crates/ksp-wallet-lib/README.md
crates/ksp-wallet-lib/USAGE.md
docs/IDEAS.md
docs/architecture/004-COMPONENT_INVENTORY.md
docs/formats/KSPWALLET_V2.md
docs/plans/013-V0_2_6_WALLET_DESK_PLAN.md
docs/validation/009-V0_2_6_WALLET_DESK_COMPLIANCE.md
prompts/011-V0_2_6_START_PROMPT.md
CHANGELOG.md reste réservé à la clôture pre.018.
Prochaine tranche
0.2.6-pre.017 doit maintenant porter la migration explicite et authentifiée V1 -> V2 :
API de migration nommée explicitement
source V1 authentifiée
nouveau document V2 cryptographiquement valide
aucune migration lors d'un open ordinaire
stratégie destination/no-clobber ou remplacement explicitement choisie
préservation identité Solana + metadata + policy VIEW applicable
canaris stale/tampering/failure atomicity
régression complète Wallet Desk V1/V2
La candidate/documentation finale reste pre.018.
Validation opérateur requise
Après application du delta :
cargo fmt --all
python3 scripts/audit_rust_workspace_rules.py
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-wallet-lib
cargo test -p ksp-app-wallet-desk
cargo test --workspace
Un contrôle fonctionnel Wallet Desk est également utile avant pre.017 :
(cd crates/ksp-app-wallet-desk && cargo tauri dev)
Vérifier au minimum :
création -> format_version 2
import -> format_version 2
inventory V1/V2
unlock OWNER/VIEW
metadata + rotations sur V2
balance depuis handle autorisé
Ne pas exécuter cargo tauri build en pre.016. Le build de production reste réservé à pre.018 et doit demeurer l'ultime opération de validation de la candidate.