v0.2.6-pre.018
This commit is contained in:
136
crates/ksp-app-wallet-desk/README.md
Normal file
136
crates/ksp-app-wallet-desk/README.md
Normal file
@@ -0,0 +1,136 @@
|
||||
<!-- file: crates/ksp-app-wallet-desk/README.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# `ksp-app-wallet-desk`
|
||||
|
||||
`ksp-app-wallet-desk` est l'application desktop spécialisée d'administration et de validation des wallets KSP.
|
||||
|
||||
La crate est un package Tauri mixte :
|
||||
|
||||
```text
|
||||
package : ksp-app-wallet-desk
|
||||
lib : ksp_app_wallet_desk_lib
|
||||
bin : ksp-app-wallet-desk
|
||||
```
|
||||
|
||||
## Responsabilités
|
||||
|
||||
Wallet Desk reste une couche d'interface et de composition. Il ne possède ni le wire `.kspwallet`, ni la cryptographie Wallet, ni la résolution Config, ni le transport Solana :
|
||||
|
||||
```text
|
||||
ksp-config-lib -> configuration/composite/.env
|
||||
ksp-wallet-lib -> format, crypto, VIEW/OWNER, import/export, migration
|
||||
ksp-onchain-transport-lib -> RPC Solana HTTP
|
||||
ksp-logging-lib -> logging/tracing applicatif
|
||||
ksp-app-wallet-desk -> orchestration Tauri + projections sûres
|
||||
```
|
||||
|
||||
Le frontend ne reçoit jamais les keypairs, ciphertexts, passwords Config, paths complets import/export ou handles VIEW/OWNER. Les opérations privilégiées sont exécutées côté Rust.
|
||||
|
||||
## `.kspwallet` V1/V2
|
||||
|
||||
La release `0.2.6` conserve V1 et ajoute V2 :
|
||||
|
||||
```text
|
||||
V1 : JSON UTF-8 historique, lecture explicite toujours supportée
|
||||
V2 : wire binaire KSP, format de création/import par défaut
|
||||
```
|
||||
|
||||
Wallet Desk consomme uniquement les APIs non versionnées de `ksp-wallet-lib` :
|
||||
|
||||
- création/import -> format par défaut `V2` ;
|
||||
- inventory/inspection/open -> détection V1/V2 ;
|
||||
- mutations OWNER/VIEW -> restent dans le format natif ouvert ;
|
||||
- ouverture d'un V1 -> aucune migration implicite.
|
||||
|
||||
`ksp-wallet-lib` conserve parallèlement les APIs explicites `_v1` / `_v2` pour les consumers qui doivent imposer un format. `DEFAULT_WALLET_FORMAT` et `LATEST_SUPPORTED_WALLET_FORMAT` sont des politiques distinctes ; l'apparition future d'un V3 n'impose donc pas de modifier automatiquement le format créé par les APIs génériques.
|
||||
|
||||
La migration V1 -> V2 est une opération explicite OWNER-authentifiée possédée par `ksp-wallet-lib`. Wallet Desk `0.2.6` ne migre jamais silencieusement un wallet lors de sa sélection, inspection ou ouverture.
|
||||
|
||||
## Capacités fonctionnelles `0.2.6`
|
||||
|
||||
La surface validée comprend :
|
||||
|
||||
- inventory root-scoped des `.kspwallet` ;
|
||||
- create/import Solana CLI JSON et Base58 ;
|
||||
- sélection et inspection locked ;
|
||||
- ouverture VIEW et OWNER, manuelle ou via candidats secrets Config ;
|
||||
- affichage Pubkey/alias/notes uniquement après autorisation ;
|
||||
- `getBalance` via le Transport HTTP KSP ;
|
||||
- mutation alias/notes OWNER ;
|
||||
- rotations OWNER et VIEW ;
|
||||
- self-rotation VIEW ;
|
||||
- disable/recreate VIEW fort par OWNER ;
|
||||
- export OWNER Solana CLI JSON/Base58 no-clobber ;
|
||||
- wire V2 par défaut tout en conservant la compatibilité V1.
|
||||
|
||||
## Frontières desktop
|
||||
|
||||
Le frontend utilise Bootstrap, Font Awesome, DataTables/Select, SimpleBar et le bridge Logging KSP. Les capabilities Tauri du guest restent minimales :
|
||||
|
||||
```text
|
||||
core:default
|
||||
tracing:default
|
||||
```
|
||||
|
||||
Les pickers import/export sont invoqués côté Rust. Aucun accès direct filesystem ou réseau Solana n'est accordé au frontend.
|
||||
|
||||
## Développement
|
||||
|
||||
Le workspace contient plusieurs applications Tauri. `-c/--config` n'est pas un sélecteur de crate ; le cycle doit être lancé depuis le répertoire applicatif :
|
||||
|
||||
```bash
|
||||
(cd crates/ksp-app-wallet-desk && cargo tauri dev)
|
||||
```
|
||||
|
||||
En développement, le launcher Rust normalise ensuite son current working directory vers la racine du workspace avant le bootstrap Config. Les chemins relatifs `config/`, `config/schemas/`, `.env`, `logs/` et `wallets/` restent ainsi cohérents avec le checkout de développement sans déplacer leur ownership hors de `ksp-config-lib`.
|
||||
|
||||
Les ports réservés sont :
|
||||
|
||||
```text
|
||||
Vite HTTP : 1432
|
||||
Vite WS : 1433
|
||||
```
|
||||
|
||||
## Runtime packagé
|
||||
|
||||
Une application distribuée ne dépend pas du checkout source ni du répertoire depuis lequel l'utilisateur lance le binaire.
|
||||
|
||||
Les documents Config et schemas enregistrés sont embarqués comme resources Tauri. Au démarrage release :
|
||||
|
||||
1. Tauri résout son répertoire de resources ;
|
||||
2. `ksp-config-lib` résout un répertoire de données utilisateur KSP writable via `ProjectDirs` ;
|
||||
3. les documents Config packagés sont copiés uniquement lorsqu'ils sont absents ;
|
||||
4. les schemas, possédés par le package courant, sont resynchronisés à chaque lancement ;
|
||||
5. le process adopte ce répertoire KSP writable comme current working directory avant `AppState::initialize`.
|
||||
|
||||
Le `.env` n'est jamais embarqué ni prérempli. Les Config déjà modifiées par l'utilisateur ne sont jamais écrasées silencieusement. Les chemins relatifs de logs et wallets restent ancrés dans ce runtime writable, sauf override explicite par Config.
|
||||
|
||||
## Validation
|
||||
|
||||
Les validations Rust courantes sont :
|
||||
|
||||
```bash
|
||||
cargo fmt --all
|
||||
python3 scripts/audit_rust_workspace_rules.py
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets
|
||||
cargo test -p ksp-app-wallet-desk
|
||||
cargo test --workspace
|
||||
```
|
||||
|
||||
Le parcours fonctionnel utilise exclusivement Tauri :
|
||||
|
||||
```bash
|
||||
(cd crates/ksp-app-wallet-desk && cargo tauri dev)
|
||||
```
|
||||
|
||||
Le build production de la release est exécuté seulement après tous les autres gates :
|
||||
|
||||
```bash
|
||||
(cd crates/ksp-app-wallet-desk && cargo tauri build)
|
||||
```
|
||||
|
||||
Cette commande doit rester l'absolue dernière opération de validation de la candidate `0.2.6`.
|
||||
|
||||
Voir également [`USAGE.md`](USAGE.md), [`../../docs/formats/KSPWALLET_V1.md`](../../docs/formats/KSPWALLET_V1.md), [`../../docs/formats/KSPWALLET_V2.md`](../../docs/formats/KSPWALLET_V2.md) et [`../../docs/validation/009-V0_2_6_WALLET_DESK_COMPLIANCE.md`](../../docs/validation/009-V0_2_6_WALLET_DESK_COMPLIANCE.md).
|
||||
140
crates/ksp-app-wallet-desk/USAGE.md
Normal file
140
crates/ksp-app-wallet-desk/USAGE.md
Normal file
@@ -0,0 +1,140 @@
|
||||
<!-- file: crates/ksp-app-wallet-desk/USAGE.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Utilisation de `ksp-app-wallet-desk`
|
||||
|
||||
## 1. Lancement de développement
|
||||
|
||||
Depuis la racine du workspace :
|
||||
|
||||
```bash
|
||||
(cd crates/ksp-app-wallet-desk && cargo tauri dev)
|
||||
```
|
||||
|
||||
Pour isoler les wallets d'un parcours manuel :
|
||||
|
||||
```bash
|
||||
KSP_WALLETS_DIRECTORY=var/wallet-desk-manual \
|
||||
bash -lc 'cd crates/ksp-app-wallet-desk && cargo tauri dev'
|
||||
```
|
||||
|
||||
Le processus Rust debug recale son current working directory sur la racine du workspace avant le bootstrap Config. `KSP_WALLETS_DIRECTORY`, les autres variables KSP et le `.env` restent résolus exclusivement par `ksp-config-lib`.
|
||||
|
||||
## 2. Format natif
|
||||
|
||||
Wallet Desk ne sélectionne pas directement une version de wire : il utilise la façade générique de `ksp-wallet-lib`.
|
||||
|
||||
```text
|
||||
nouveau wallet -> V2
|
||||
import Solana CLI/Base58 -> V2
|
||||
inspection/ouverture -> auto-détection V1/V2
|
||||
mutation d'un V1 ouvert -> V1
|
||||
mutation d'un V2 ouvert -> V2
|
||||
```
|
||||
|
||||
La présence de V2 ne réécrit pas automatiquement les fichiers V1 existants.
|
||||
|
||||
## 3. Création / import
|
||||
|
||||
Dans **Create / Import** :
|
||||
|
||||
- la création génère une nouvelle identité Solana et un `.kspwallet` V2 ;
|
||||
- l'import accepte les formats de transfert Solana retenus, puis crée un `.kspwallet` V2 ;
|
||||
- OWNER est toujours requis ; VIEW est optionnel ;
|
||||
- les passwords sont request-only et ne sont jamais renvoyés par IPC.
|
||||
|
||||
L'import natif utilise un picker Rust. Le path source complet et les bytes de keypair ne traversent pas le frontend.
|
||||
|
||||
## 4. Inventory et ouverture
|
||||
|
||||
L'inventory n'affiche que des projections locked sûres. La sélection ne déverrouille jamais automatiquement un secret Config.
|
||||
|
||||
L'ouverture peut ensuite utiliser :
|
||||
|
||||
- un password saisi manuellement ;
|
||||
- un candidat secret Config explicitement sélectionné côté backend.
|
||||
|
||||
VIEW et OWNER produisent des handles Rust-only. La Pubkey, l'alias et les notes ne sont projetés qu'après autorisation.
|
||||
|
||||
## 5. Administration
|
||||
|
||||
OWNER permet notamment :
|
||||
|
||||
- modifier l'alias ;
|
||||
- ajouter/modifier/supprimer des notes ;
|
||||
- changer le password OWNER ;
|
||||
- changer, désactiver ou recréer VIEW ;
|
||||
- exporter la keypair en Solana CLI JSON ou Base58.
|
||||
|
||||
VIEW peut effectuer sa self-rotation lorsqu'il est actif. Les opérations destructives/privilégiées utilisent les modals Bootstrap du shell et non `window.confirm`/`alert`.
|
||||
|
||||
## 6. Migration V1 -> V2
|
||||
|
||||
La migration existe dans `ksp-wallet-lib`, mais n'est jamais un effet secondaire d'une ouverture Wallet Desk.
|
||||
|
||||
Les APIs bibliothèque dédiées sont :
|
||||
|
||||
```text
|
||||
migrate_wallet_v1_to_v2
|
||||
migrate_wallet_file_v1_to_v2
|
||||
migrate_wallet_file_v1_to_v2_in_place
|
||||
```
|
||||
|
||||
Elles authentifient OWNER, reconstruisent un document cryptographique V2 neuf et conservent l'identité Solana ainsi que les metadata/note IDs. Lorsque VIEW est activé, un password VIEW cible doit être fourni. La copie est no-clobber ; le remplacement in-place est stale-protected.
|
||||
|
||||
## 7. Balance Solana
|
||||
|
||||
Une session VIEW ou OWNER autorisée peut demander `getBalance` via `ksp-onchain-transport-lib`. Le frontend ne choisit ni Pubkey arbitraire ni URL RPC : ces valeurs sont dérivées de l'état Rust autorisé et de Config.
|
||||
|
||||
## 8. Runtime packagé
|
||||
|
||||
En build release, les Config/schemas enregistrés sont des resources du bundle Tauri. Avant le bootstrap applicatif, `ksp-config-lib` prépare un répertoire de données utilisateur commun à KSP :
|
||||
|
||||
```text
|
||||
<runtime KSP writable>/
|
||||
├── config/
|
||||
│ ├── composite.ksp-app-wallet-desk.json
|
||||
│ ├── std.logging.json
|
||||
│ ├── std.transport.json
|
||||
│ ├── std.wallet.json
|
||||
│ └── schemas/
|
||||
├── .env # créé/modifié uniquement par Config si nécessaire
|
||||
├── logs/ # par défaut si path relatif
|
||||
└── wallets/ # par défaut si path relatif
|
||||
```
|
||||
|
||||
Le chemin physique exact dépend de la plateforme et est résolu par `ProjectDirs`; l'application ne suppose aucune home directory particulière.
|
||||
|
||||
Les Config existantes sont conservées lors d'une mise à jour. Les schemas sont synchronisés depuis le package courant. Le `.env` et les secrets ne sont jamais embarqués dans le bundle.
|
||||
|
||||
## 9. Validation candidate `0.2.6`
|
||||
|
||||
Avant le build :
|
||||
|
||||
```bash
|
||||
cargo fmt --all
|
||||
python3 scripts/audit_rust_workspace_rules.py
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets
|
||||
cargo test -p ksp-config-lib
|
||||
cargo test -p ksp-wallet-lib
|
||||
cargo test -p ksp-app-config-desk
|
||||
cargo test -p ksp-app-wallet-desk
|
||||
cargo test --workspace
|
||||
```
|
||||
|
||||
Puis parcours fonctionnel :
|
||||
|
||||
```bash
|
||||
(cd crates/ksp-app-wallet-desk && cargo tauri dev)
|
||||
```
|
||||
|
||||
Le smoke Devnet opt-in, s'il est rejoué, doit l'être avant le build final.
|
||||
|
||||
L'absolue dernière opération est :
|
||||
|
||||
```bash
|
||||
(cd crates/ksp-app-wallet-desk && cargo tauri build)
|
||||
```
|
||||
|
||||
Aucune commande de validation ne doit être exécutée après ce build pour conserver la preuve d'ordre de la candidate.
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: crates/ksp-app-wallet-desk/frontend/main.html -->
|
||||
<!-- version: 2 -->
|
||||
<!-- version: 3 -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
@@ -53,7 +53,7 @@
|
||||
<h1 id="viewTitle" class="h3 mb-1">Dashboard</h1>
|
||||
<p class="text-body-secondary mb-0">Identité autorisée et balance SOL via le Transport HTTP composite sont actives.</p>
|
||||
</div>
|
||||
<span class="badge text-bg-secondary">0.2.6-pre.14.fix.1</span>
|
||||
<span class="badge text-bg-secondary">0.2.6-pre.18</span>
|
||||
</div>
|
||||
<section data-view-panel="dashboard">
|
||||
<div class="row g-3">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ksp-app-wallet-desk",
|
||||
"private": true,
|
||||
"version": "0.2.6-pre.14.fix.1",
|
||||
"version": "0.2.6-pre.18",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-wallet-desk/src/tauri.rs
|
||||
// version: 10
|
||||
// version: 11
|
||||
|
||||
//! Tauri runtime assembly for the KSP wallet desktop application.
|
||||
|
||||
@@ -8,6 +8,11 @@ use tauri_plugin_dialog::DialogExt; // rust-rules: trait-import
|
||||
/// Runs the Wallet Desk application.
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result<()> {
|
||||
let context = tauri::generate_context!();
|
||||
let runtime_layout = configure_packaged_runtime(&context);
|
||||
if let std::result::Result::Err(error) = runtime_layout {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
let app_state = crate::AppState::initialize(arguments);
|
||||
let app_state = match app_state {
|
||||
std::result::Result::Ok(value) => value,
|
||||
@@ -18,7 +23,7 @@ pub fn run(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result<()> {
|
||||
builder = configure_plugins(builder);
|
||||
builder = configure_commands(builder);
|
||||
builder = configure_setup(builder);
|
||||
let run_result = builder.run(tauri::generate_context!());
|
||||
let run_result = builder.run(context);
|
||||
return match run_result {
|
||||
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
||||
std::result::Result::Err(error) => std::result::Result::Err(
|
||||
@@ -28,6 +33,36 @@ pub fn run(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result<()> {
|
||||
};
|
||||
}
|
||||
|
||||
fn configure_packaged_runtime(context: &tauri::Context<tauri::Wry>) -> ksp_core_lib::Result<()> {
|
||||
if cfg!(debug_assertions) {
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
let resource_root = tauri::utils::platform::resource_dir(context.package_info(), &tauri::Env::default());
|
||||
let resource_root = match resource_root {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => {
|
||||
return std::result::Result::Err(
|
||||
ksp_core_lib::Error::new(crate::ERROR_CODE_TAURI_RUNTIME_FAILED, "Cannot resolve packaged Tauri resource directory")
|
||||
.with_context("tauri_error", error.to_string()),
|
||||
);
|
||||
},
|
||||
};
|
||||
let layout = ksp_config_lib::prepare_packaged_runtime(resource_root.as_path());
|
||||
let layout = match layout {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let working_directory = std::env::set_current_dir(layout.runtime_root());
|
||||
return match working_directory {
|
||||
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
||||
std::result::Result::Err(error) => std::result::Result::Err(
|
||||
ksp_core_lib::Error::new(crate::ERROR_CODE_TAURI_RUNTIME_FAILED, "Cannot activate packaged KSP runtime directory")
|
||||
.with_context("runtime_root", layout.runtime_root().to_string_lossy().into_owned())
|
||||
.with_source(error),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
fn configure_state(builder: tauri::Builder<tauri::Wry>, app_state: crate::AppState) -> tauri::Builder<tauri::Wry> {
|
||||
return builder.manage(app_state);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "KSP Wallet Desk",
|
||||
"version": "0.2.6-pre.14.fix.1",
|
||||
"version": "0.2.6-pre.18",
|
||||
"identifier": "com.sasedev.ksp-app-wallet-desk",
|
||||
"build": {
|
||||
"beforeDevCommand": {
|
||||
@@ -51,6 +51,16 @@
|
||||
"icon": [
|
||||
"icons/favicon.png",
|
||||
"icons/favicon.ico"
|
||||
]
|
||||
],
|
||||
"resources": {
|
||||
"../../config/composite.ksp-app-wallet-desk.json": "config/composite.ksp-app-wallet-desk.json",
|
||||
"../../config/std.logging.json": "config/std.logging.json",
|
||||
"../../config/std.transport.json": "config/std.transport.json",
|
||||
"../../config/std.wallet.json": "config/std.wallet.json",
|
||||
"../../config/schemas/composite.schema.json": "config/schemas/composite.schema.json",
|
||||
"../../config/schemas/std.logging.schema.json": "config/schemas/std.logging.schema.json",
|
||||
"../../config/schemas/std.transport.schema.json": "config/schemas/std.transport.schema.json",
|
||||
"../../config/schemas/std.wallet.schema.json": "config/schemas/std.wallet.schema.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-wallet-desk/tests/desktop_contract.rs
|
||||
// version: 19
|
||||
// version: 20
|
||||
|
||||
//! Desktop build, shell and Config-status contract audits for Wallet Desk.
|
||||
|
||||
@@ -417,3 +417,31 @@ fn pre_017_wallet_desk_open_paths_remain_non_migrating() {
|
||||
assert!(state.contains("ksp_wallet_lib::open_wallet_owner_file"));
|
||||
assert!(inventory.contains("ksp_wallet_lib::inspect_locked_wallet_file"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_018_packaged_runtime_bundles_config_resources_and_keeps_wallet_desk_version_current() {
|
||||
let root = app_root();
|
||||
let tauri = read_json(root.join("tauri.conf.json").as_path());
|
||||
assert_eq!(tauri.pointer("/version").and_then(serde_json::Value::as_str), std::option::Option::Some("0.2.6-pre.18"));
|
||||
let package = read_json(root.join("package.json").as_path());
|
||||
assert_eq!(package.pointer("/version").and_then(serde_json::Value::as_str), std::option::Option::Some("0.2.6-pre.18"));
|
||||
let resources = tauri.pointer("/bundle/resources").and_then(serde_json::Value::as_object);
|
||||
assert!(resources.is_some(), "packaged Wallet Desk Config resources map must exist");
|
||||
if let std::option::Option::Some(resources) = resources {
|
||||
assert_eq!(resources.len(), 8);
|
||||
assert_eq!(
|
||||
resources.get("../../config/composite.ksp-app-wallet-desk.json").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some("config/composite.ksp-app-wallet-desk.json"),
|
||||
);
|
||||
assert_eq!(
|
||||
resources.get("../../config/schemas/composite.schema.json").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some("config/schemas/composite.schema.json"),
|
||||
);
|
||||
}
|
||||
let main = read_text(root.join("frontend/main.html").as_path());
|
||||
assert!(main.contains("0.2.6-pre.18"));
|
||||
let tauri_source = read_text(root.join("src/tauri.rs").as_path());
|
||||
assert!(tauri_source.contains("ksp_config_lib::prepare_packaged_runtime"));
|
||||
assert!(tauri_source.contains("tauri::utils::platform::resource_dir"));
|
||||
assert!(tauri_source.contains("std::env::set_current_dir(layout.runtime_root())"));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-wallet-desk/tests/release_compliance.rs
|
||||
// version: 3
|
||||
// version: 4
|
||||
|
||||
//! Release-wide deterministic compliance canaries for Wallet Desk.
|
||||
|
||||
@@ -181,3 +181,36 @@ fn wallet_desk_dependency_firewall_and_tauri_capabilities_are_minimal() {
|
||||
assert!(!capability_source.contains("dialog:"));
|
||||
assert!(!capability_source.contains("fs:"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn packaged_resources_include_only_registered_config_sources_and_schemas() {
|
||||
let root = app_root();
|
||||
let tauri_source = read_text(root.join("tauri.conf.json").as_path());
|
||||
let tauri = serde_json::from_str::<serde_json::Value>(tauri_source.as_str());
|
||||
assert!(tauri.is_ok(), "Wallet Desk Tauri config should parse");
|
||||
let tauri = match tauri {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let resources = tauri.pointer("/bundle/resources").and_then(serde_json::Value::as_object);
|
||||
assert!(resources.is_some(), "Wallet Desk package must declare Config resources");
|
||||
let resources = match resources {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
assert_eq!(resources.len(), 8);
|
||||
for (source, destination) in resources {
|
||||
let destination = destination.as_str();
|
||||
assert!(destination.is_some(), "resource destination must be textual");
|
||||
let destination = match destination {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => continue,
|
||||
};
|
||||
assert!(source.starts_with("../../config/"));
|
||||
assert!(destination.starts_with("config/"));
|
||||
for forbidden in [".env", "wallets", "logs", "secret", "private"] {
|
||||
assert!(!source.contains(forbidden), "mutable/secret runtime resource must not be bundled: {source}");
|
||||
assert!(!destination.contains(forbidden), "mutable/secret runtime destination must not be bundled: {destination}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user