8.9 KiB
Workspace Restructuring Plan
Overview
This document outlines the plan to restructure the Sharenet Passport project into a Cargo workspace with a library crate (sharenet-passport) and a CLI wrapper crate (sharenet-passport-cli). The goal is to enable reuse of the core passport functionality in multiple contexts (CLI, web/WASM, embedded) while maintaining Clean Architecture principles.
Target Architecture
Workspace Structure
sharenet-passport-creator/
├── Cargo.toml # Workspace manifest
├── sharenet-passport/ # Library crate (core functionality)
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ ├── domain/
│ ├── application/
│ └── infrastructure/
├── sharenet-passport-cli/ # CLI crate (command-line interface)
│ ├── Cargo.toml
│ └── src/
│ ├── main.rs
│ ├── cli/
│ └── interface/
└── docs/
Implementation Details
1. Workspace Configuration
Root Cargo.toml:
[workspace]
members = ["sharenet-passport", "sharenet-passport-cli"]
resolver = "2"
[workspace.dependencies]
# Common dependencies shared across workspace members
bip39 = "2.1"
ed25519-dalek = { version = "2.1", features = ["serde"] }
chacha20poly1305 = "0.10"
hkdf = "0.12"
sha2 = "0.10"
rand = "0.8"
rand_core = "0.6"
serde = { version = "1.0", features = ["derive"] }
serde_cbor = "0.11"
thiserror = "1.0"
zeroize = { version = "1.7", features = ["zeroize_derive"] }
hex = "0.4"
2. Library Crate (sharenet-passport)
Purpose: Core passport creation, management, and verification functionality
sharenet-passport/Cargo.toml:
[package]
name = "sharenet-passport"
version = "0.1.0"
edition = "2021"
description = "Core library for Sharenet Passport creation and management"
authors = ["Your Name <your.email@example.com>"]
license = "MIT OR Apache-2.0"
repository = "https://git.sharenet.sh/your-org/sharenet-passport"
[dependencies]
# Inherit from workspace dependencies
bip39.workspace = true
ed25519-dalek.workspace = true
chacha20poly1305.workspace = true
hkdf.workspace = true
sha2.workspace = true
rand.workspace = true
rand_core.workspace = true
serde.workspace = true
serde_cbor.workspace = true
thiserror.workspace = true
zeroize.workspace = true
hex.workspace = true
[lib]
crate-type = ["cdylib", "rlib"] # Support both native and WASM
[features]
default = ["std"]
std = [] # Standard library support
alloc = [] # No-std with alloc support
wasm = ["alloc"] # WASM target support
[publish]
registry = "sharenet"
3. CLI Crate (sharenet-passport-cli)
Purpose: Command-line interface wrapper around the library
sharenet-passport-cli/Cargo.toml:
[package]
name = "sharenet-passport-cli"
version = "0.1.0"
edition = "2021"
description = "CLI interface for Sharenet Passport"
authors = ["Your Name <your.email@example.com>"]
[dependencies]
sharenet-passport = { path = "../sharenet-passport" }
clap = { version = "4.4", features = ["derive"] }
rpassword = "7.2"
[dev-dependencies]
assert_matches = "1.5"
tempfile = "3.8"
Clean Architecture Preservation
Domain Layer (Pure Business Logic)
Location: sharenet-passport/src/domain/
Characteristics:
- Pure Rust, no external dependencies
- No I/O operations
- WASM-compatible
- Contains entities, traits, and domain errors
Key Files:
entities.rs- Core data structures (Passport, RecoveryPhrase, etc.)traits.rs- Abstract interfaces (MnemonicGenerator, KeyDeriver, etc.)error.rs- Domain-specific errors
Application Layer (Use Cases)
Location: sharenet-passport/src/application/
Characteristics:
- Generic over infrastructure traits
- Orchestrates domain and infrastructure
- No concrete implementations
- Dependency injection via traits
Key Files:
use_cases.rs- Business use cases (CreatePassport, Import, Export, etc.)error.rs- Application-specific errors
Infrastructure Layer (Platform Implementations)
Location: sharenet-passport/src/infrastructure/
Characteristics:
- Concrete implementations of domain traits
- Platform-specific code
- Optional features via conditional compilation
- Separate modules for different concerns
Key Files:
crypto.rs- Cryptographic implementationsstorage.rs- File system operations
Code Organization
Library Public API (sharenet-passport/src/lib.rs)
// Re-export public API
pub mod domain;
pub mod application;
pub mod infrastructure;
// Public API surface
pub use domain::entities::{Passport, RecoveryPhrase, PassportFile};
pub use domain::traits::{MnemonicGenerator, KeyDeriver, FileEncryptor, FileStorage};
pub use application::use_cases::{
CreatePassportUseCase,
ImportFromRecoveryUseCase,
ImportFromFileUseCase,
ExportPassportUseCase,
SignCardUseCase
};
pub use infrastructure::{
Bip39MnemonicGenerator,
Ed25519KeyDeriver,
XChaCha20FileEncryptor,
FileSystemStorage
};
CLI Entry Point (sharenet-passport-cli/src/main.rs)
use sharenet_passport::{
application::use_cases::*,
infrastructure::*,
domain::entities::*
};
// CLI-specific code remains here
mod cli;
mod interface;
use clap::Parser;
use crate::cli::commands::{Cli, Commands};
use crate::cli::interface::CliInterface;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = Cli::parse();
let interface = CliInterface::new();
// CLI command handling
match cli.command {
Commands::Create { output } => {
interface.handle_create(&output)?;
}
// ... other commands
}
Ok(())
}
Feature Flags Strategy
Library Features
std(default): Standard library features including file I/Oalloc: No-std with allocator support for embedded systemswasm: WASM-specific optimizations and bindings
Usage Examples
For Web/WASM Applications:
sharenet-passport = { version = "0.1", default-features = false, features = ["wasm"] }
For Embedded Systems:
sharenet-passport = { version = "0.1", default-features = false, features = ["alloc"] }
For CLI Applications:
sharenet-passport = { version = "0.1" } # Uses default std features
Private Registry Configuration
Cargo Configuration
Add to ~/.cargo/config.toml:
[registries.sharenet]
index = "https://git.sharenet.sh/api/v1/crates/{crate}/index"
Publishing
cd sharenet-passport
cargo publish --registry sharenet
Benefits
1. Reusability
- CLI: Full command-line interface
- Web/WASM: Browser-based passport management
- Embedded: Resource-constrained environments
- Mobile: Native mobile applications
2. Maintainability
- Clear separation of concerns
- Independent versioning of library vs CLI
- Shared dependency management
- Easier testing and mocking
3. Deployment Flexibility
- Library can be published to private registry
- CLI can be distributed as standalone binary
- Web components can be compiled to WASM
- Embedded systems can use minimal features
4. Development Workflow
- Shared code changes affect all consumers
- Independent development of CLI features
- Parallel testing of different components
- Clear API boundaries
Usage Examples
Web Application Usage
use sharenet_passport::{
domain::entities::Passport,
application::use_cases::CreatePassportUseCase,
infrastructure::{Bip39MnemonicGenerator, Ed25519KeyDeriver}
};
// Web-specific infrastructure implementations
struct WebFileEncryptor;
struct WebStorage;
impl FileEncryptor for WebFileEncryptor { /* ... */ }
impl FileStorage for WebStorage { /* ... */ }
let use_case = CreatePassportUseCase::new(
Bip39MnemonicGenerator,
Ed25519KeyDeriver,
WebFileEncryptor,
WebStorage,
);
CLI Usage (Unchanged)
# Existing CLI commands continue to work
sharenet-passport-cli create --output my-passport.spf
sharenet-passport-cli import-recovery --output restored.spf
sharenet-passport-cli info --file passport.spf
Testing Strategy
Library Tests
- Unit tests for domain logic
- Integration tests for use cases
- WASM tests using
wasm-bindgen-test - Feature-flag specific tests
CLI Tests
- End-to-end command tests
- File system integration tests
- Cross-platform compatibility tests
- User interaction tests
Migration Considerations
Backward Compatibility
- Existing CLI commands remain unchanged
- File formats remain compatible
- API surface remains stable
- Documentation updates minimal
Development Impact
- Shared workspace dependencies
- Unified build process
- Consistent testing approach
- Clear separation of library vs CLI concerns
This restructuring enables the Sharenet Passport core functionality to be reused across multiple platforms while maintaining the Clean Architecture principles and enabling private registry publishing to git.sharenet.sh.