| ← Back to Main Documentation | Core Systems Index |
Plings HD Wallet Management Architecture
Created: Sön 13 Jul 2025 00:17:00 CEST
Version: 2.0 - Wallet-First Design
Status: Production Architecture
Overview
The Plings HD Wallet Management Architecture implements a wallet-first design where wallet versions serve as the primary organizational structure for all cryptographic operations. This architecture enables secure key management, seamless transitions during security incidents, and multi-environment support while maintaining backward compatibility.
Core Principle: Wallet Versions as Top-Level Hierarchy
Architectural Philosophy
Traditional Approach (Deprecated):
Master Key → Manufacturer → Products
Plings Wallet-First Approach (Current):
Master Key → Wallet Version → Manufacturer → Products
This inversion places wallet security and versioning at the foundation, enabling:
- Clean key rotation without disrupting manufacturer hierarchies
- Multi-environment support (development, testing, production)
- Progressive security evolution from centralized to distributed key management
- Incident response capabilities with automated key compromise handling
HD Wallet Structure
Solana Standard Hierarchy (SLIP-0044)
m/44'/501'/ (Solana Standard Base)
├── 1' → Wallet v1 (Current Production)
│ ├── 1/ → Plings (Manufacturer Index 1)
│ │ ├── 1/ → Generic Tags (Category 1)
│ │ ├── 2/ → Test Batches (Category 2)
│ │ └── 3/ → Manufacturer Batches (Category 3)
│ ├── 2/ → IKEA (Manufacturer Index 2)
│ │ ├── 1/ → Mountain Bikes (Category 1, Class Pointer: 3K7mX9abDcE)
│ │ ├── 2/ → Furniture (Category 2, Class Pointer: 4K7mX9abDcE)
│ │ └── 3/ → Tools (Category 3, Class Pointer: 5K7mX9abDcE)
│ ├── 3/ → Coca-Cola (Manufacturer Index 3)
│ │ ├── 1/ → Classic Products (Category 1, Class Pointer: 2rt5KqL9mXw)
│ │ ├── 2/ → Diet Products (Category 2, Class Pointer: jj9QmRxPtK8)
│ │ └── 3/ → Energy Products (Category 3, Class Pointer: 7K8mX9abDcE)
│ └── 4-999/ → Additional Manufacturers
├── 2' → Wallet v2 (Post-Key-Compromise)
│ ├── 1/ → Plings (New Wallet)
│ ├── 2/ → IKEA (Migrated to New Wallet)
│ ├── 3/ → Coca-Cola (Migrated to New Wallet)
│ └── 4-999/ → Other Manufacturers (Migrated)
├── 3' → Wallet v3 (Development/Testing)
│ ├── 1/ → Plings Dev Environment
│ ├── 10/ → Test Manufacturer A
│ └── 11/ → Test Manufacturer B
└── 4-999' → Future Wallet Versions
Path Examples with Wallet Context
Wallet v1 (Current Production)
# Plings Generic Tag
Path: 2.2.2.2.2
Class Pointer: 4K7mX9abDcE
HD Derivation: m/44'/501'/1'/1'/1'/1'/1'/1'
URL: https://s.plings.io?t=q&p=2.2.2.2.2&cp=4K7mX9abDcE&i=<solana_address>
# IKEA Mountain Bike Instance
Path: 2.3.2.7P.9j
Class Pointer: 3K7mX9abDcE
HD Derivation: m/44'/501'/1'/2'/1'/2024'/158'
URL: https://s.plings.io?t=q&p=2.3.2.7P.9j&cp=3K7mX9abDcE&i=<solana_address>
# Coca-Cola Classic Instance
Path: 2.3j.4.5Q.3L8z
Class Pointer: 2rt5KqL9mXw
HD Derivation: m/44'/501'/1'/3'/1255'/5847'/90000'
URL: https://s.plings.io?t=q&p=2.3j.4.5Q.3L8z&cp=2rt5KqL9mXw&i=<solana_address>
Wallet v2 (Post-Compromise Migration)
# Same logical paths, different wallet version
Path: 2.2.2.2.2 (Wallet v2)
Class Pointer: 4K7mX9abDcE (same as v1)
HD Derivation: m/44'/501'/2'/1'/1'/1'/1'/1'
URL: https://s.plings.io?t=q&p=2.2.2.2.2&cp=4K7mX9abDcE&i=<solana_address>
# IKEA Mountain Bike in New Wallet
Path: 2.3.2.7P.9j (Wallet v2)
Class Pointer: 3K7mX9abDcE (same as v1)
HD Derivation: m/44'/501'/2'/2'/1'/2024'/158'
URL: https://s.plings.io?t=q&p=2.3.2.7P.9j&cp=3K7mX9abDcE&i=<solana_address>
Wallet v3 (Development Environment)
# Development Testing
Path: 2.3.2.2.2 (Wallet v3)
Class Pointer: 6K7mX9abDcE (development class)
HD Derivation: m/44'/501'/3'/1'/2'/1'/1'/1'
URL: https://s.plings.io?t=q&p=2.3.2.2.2&cp=6K7mX9abDcE&i=<solana_address>
Database Architecture
Core Tables Structure
1. Wallet Versions Registry
CREATE TABLE wallet_versions (
version_id INTEGER PRIMARY KEY,
version_name VARCHAR(10) NOT NULL UNIQUE, -- "v1", "v2", "v3", etc.
master_key_id VARCHAR(100) NOT NULL, -- HSM key reference
description TEXT, -- "Production wallet", "Post-compromise v2"
environment VARCHAR(20) DEFAULT 'production', -- "production", "testing", "development"
security_level VARCHAR(20) DEFAULT 'standard', -- "standard", "high", "experimental"
status VARCHAR(20) DEFAULT 'active', -- "active", "compromised", "deprecated", "retired"
created_at TIMESTAMP DEFAULT NOW(),
compromised_at TIMESTAMP, -- When key compromise was detected
retired_at TIMESTAMP, -- When wallet was fully retired
is_default BOOLEAN DEFAULT FALSE, -- Only one default wallet allowed
-- Constraints
CONSTRAINT unique_version_name UNIQUE (version_name),
CONSTRAINT unique_default_wallet
EXCLUDE (is_default WITH =) WHERE (is_default = true),
-- Indexes
INDEX idx_wallet_status (status),
INDEX idx_wallet_environment (environment),
INDEX idx_wallet_default (is_default) WHERE (is_default = true)
);
-- Initialize production wallet v1
INSERT INTO wallet_versions (
version_id, version_name, master_key_id, description,
environment, status, is_default
) VALUES (
1, 'v1', 'plings_master_key_v1', 'Initial production wallet',
'production', 'active', true
);
2. Enhanced Manufacturer Registry
CREATE TABLE manufacturer_registry (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
wallet_version INTEGER NOT NULL REFERENCES wallet_versions(version_id),
manufacturer_index INTEGER NOT NULL, -- Index within this wallet (1=Plings, 2+=Others)
manufacturer_name VARCHAR(100) NOT NULL, -- "Plings", "IKEA", "Coca-Cola"
organization_id UUID, -- Link to organization
public_key TEXT, -- Ed25519 public key if delegated
key_delegation_level VARCHAR(20) DEFAULT 'none', -- "none", "verification", "full"
status VARCHAR(20) DEFAULT 'active', -- "active", "suspended", "migrating", "retired"
registered_by UUID NOT NULL,
registered_at TIMESTAMP DEFAULT NOW(),
migrated_from_wallet INTEGER, -- Previous wallet version (for migration tracking)
migration_completed_at TIMESTAMP,
-- Constraints
CONSTRAINT unique_manufacturer_per_wallet
UNIQUE (wallet_version, manufacturer_index),
CONSTRAINT unique_name_per_wallet
UNIQUE (wallet_version, manufacturer_name),
CONSTRAINT check_plings_index_one
CHECK (manufacturer_name != 'Plings' OR manufacturer_index = 1),
-- Foreign Keys
FOREIGN KEY (organization_id) REFERENCES organizations(id),
FOREIGN KEY (registered_by) REFERENCES users(id),
FOREIGN KEY (migrated_from_wallet) REFERENCES wallet_versions(version_id),
-- Indexes
INDEX idx_manufacturer_wallet_name (wallet_version, manufacturer_name),
INDEX idx_manufacturer_organization (organization_id),
INDEX idx_manufacturer_status (status)
);
-- Initialize Plings as manufacturer #1 in wallet v1
INSERT INTO manufacturer_registry (
wallet_version, manufacturer_index, manufacturer_name,
status, registered_by
) VALUES (
1, 1, 'Plings', 'active', '00000000-0000-0000-0000-000000000000'
);
3. Enhanced Path Registry
CREATE TABLE path_registry (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
wallet_version INTEGER NOT NULL REFERENCES wallet_versions(version_id),
path VARCHAR(50) NOT NULL, -- e.g., "2.2.2", "2.3.2.9j" (class pointer separate)
hd_derivation VARCHAR(100) NOT NULL, -- e.g., "m/44'/501'/1'/1'/1'/1'"
allocation_type VARCHAR(20) NOT NULL, -- "generic", "test", "manufacturer", "development"
manufacturer_name VARCHAR(100), -- For manufacturer batch allocations
batch_name VARCHAR(100), -- Human-readable batch identifier
quantity INTEGER, -- Number of identifiers in this allocation
purpose TEXT, -- Description/notes
status VARCHAR(20) DEFAULT 'active', -- "active", "exhausted", "migrated", "retired"
allocated_by UUID NOT NULL,
allocated_at TIMESTAMP DEFAULT NOW(),
completed_at TIMESTAMP, -- When batch generation completed
migrated_to_wallet INTEGER, -- Target wallet for migration
migrated_at TIMESTAMP, -- When migration completed
-- Constraints
CONSTRAINT unique_path_per_wallet
UNIQUE (wallet_version, path),
-- Foreign Keys
FOREIGN KEY (allocated_by) REFERENCES users(id),
FOREIGN KEY (migrated_to_wallet) REFERENCES wallet_versions(version_id),
-- Indexes
INDEX idx_path_wallet_path (wallet_version, path),
INDEX idx_path_allocation_type (allocation_type),
INDEX idx_path_manufacturer (manufacturer_name),
INDEX idx_path_status (status)
);
4. Manufacturer Migration Tracking
CREATE TABLE manufacturer_lineage (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
canonical_name VARCHAR(100) NOT NULL, -- "IKEA", "Coca-Cola" (consistent across wallets)
current_wallet_version INTEGER NOT NULL,
current_manufacturer_index INTEGER NOT NULL,
predecessor_wallet INTEGER, -- Previous wallet version
predecessor_index INTEGER, -- Previous manufacturer index
migration_reason VARCHAR(50), -- "key_compromise", "security_upgrade", "environment_separation"
migration_date TIMESTAMP DEFAULT NOW(),
migration_status VARCHAR(20) DEFAULT 'active', -- "active", "in_progress", "completed"
migration_completion_percentage INTEGER DEFAULT 0, -- 0-100% for tracking progress
-- Foreign Keys
FOREIGN KEY (current_wallet_version, current_manufacturer_index)
REFERENCES manufacturer_registry(wallet_version, manufacturer_index),
FOREIGN KEY (predecessor_wallet) REFERENCES wallet_versions(version_id),
-- Constraints
CONSTRAINT unique_canonical_manufacturer UNIQUE (canonical_name),
-- Indexes
INDEX idx_lineage_canonical (canonical_name),
INDEX idx_lineage_current_wallet (current_wallet_version),
INDEX idx_lineage_migration_status (migration_status)
);
Key Management Architecture
Three-Tier Key Storage Strategy
Plings implements a progressive three-tier key management approach that balances immediate deployment needs with long-term security requirements:
Tier Overview
| Tier | Solution | Timeline | Cost | Security Level | Use Case |
|---|---|---|---|---|---|
| Initial | Vercel Environment Variables | Immediate | $0 | Software-based | MVP, early customers |
| Next Level | SoftHSM | 2-4 weeks | $20-50/mo | HSM-equivalent | Growing business |
| Final Level | Hardware HSM | 6-9 months | $1,500-5,000/mo | Hardware-certified | Enterprise |
Tier 1: Vercel Environment Variables (Current)
Implementation:
// Initial tier - Vercel environment variables
class VercelKeyManager {
constructor() {
this.masterKey = process.env.PLINGS_MASTER_KEY; // Base58 encoded
this.walletVersion = parseInt(process.env.PLINGS_DEFAULT_WALLET || '1');
}
async deriveKey(path) {
// HD wallet derivation in API functions
const wallet = new PlingsHDWallet(this.masterKey);
const keyPair = wallet.deriveKey(path);
// Return only public key, discard private key
return {
publicKey: keyPair.publicKey,
// Private key is never stored or transmitted
};
}
}
Security Model:
- Master key encrypted by Vercel infrastructure
- Private keys derived on-demand, never stored
- Environment-specific key isolation
- Suitable for immediate production deployment
Tier 2: SoftHSM (Next Level)
Implementation:
// Next level - SoftHSM with PKCS#11
class SoftHSMKeyManager {
constructor() {
this.hsmEndpoint = process.env.HSM_ENDPOINT;
this.apiKey = process.env.HSM_API_KEY;
}
async deriveKey(path) {
// Call dedicated HSM service
const response = await fetch(`${this.hsmEndpoint}/api/derive-key`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ path })
});
return await response.json();
}
}
Security Model:
- PKCS#11 standard interface
- Keys never leave HSM boundary
- Full audit trail for compliance
- Hardware-equivalent security
Tier 3: Hardware HSM (Final Level)
Implementation:
class PlingsHardwareHSMManager:
"""
Hardware Security Module integration for enterprise-grade key management.
Architecture:
- Each wallet version has a unique master key stored in HSM
- Keys are never extractable from HSM
- Derivation operations performed within HSM when possible
- Backup keys stored in geographically separate HSMs
"""
def __init__(self, hsm_config: Dict[str, str]):
self.primary_hsm = CloudHSM(hsm_config['primary_endpoint'])
self.backup_hsm = CloudHSM(hsm_config['backup_endpoint'])
self.wallet_versioning = hsm_config.get('wallet_versioning', True)
### Migration Strategy Between Tiers
#### Tier Progression Path
Initial Tier (Vercel) → Next Level (SoftHSM) → Final Level (Hardware HSM) ↓ ↓ ↓ Immediate 2-4 weeks 6-9 months $0 cost $20-50/mo $1,500-5,000/mo MVP ready Enhanced security Enterprise grade
#### Migration Triggers
**Vercel → SoftHSM Migration**:
- Customer base > 1,000 organizations
- Security audit requirements
- Need for audit trails
- Compliance requirements
**SoftHSM → Hardware HSM Migration**:
- Enterprise customer mandates
- Regulatory compliance (FIPS 140-2)
- Revenue > $1M annually
- Geographic redundancy requirements
#### Zero-Downtime Migration Process
```javascript
// Dual-mode operation during migration
class TieredKeyManager {
constructor() {
this.currentTier = process.env.KEY_MANAGEMENT_TIER || 'vercel';
this.nextTier = process.env.MIGRATION_TARGET_TIER;
this.migrationPhase = process.env.MIGRATION_PHASE || 'none';
}
async deriveKey(path) {
switch (this.migrationPhase) {
case 'testing':
// Test new tier alongside current
const [current, next] = await Promise.all([
this.deriveWithTier(this.currentTier, path),
this.deriveWithTier(this.nextTier, path)
]);
this.validateConsistency(current, next);
return current;
case 'gradual':
// Gradual rollout based on user/batch criteria
const useNextTier = this.shouldUseNextTier(path);
return this.deriveWithTier(useNextTier ? this.nextTier : this.currentTier, path);
case 'complete':
// Full migration to new tier
return this.deriveWithTier(this.nextTier, path);
default:
// Normal operation
return this.deriveWithTier(this.currentTier, path);
}
}
}
Wallet Version Continuity
Critical: Wallet versions remain consistent across all tiers:
- Wallet v1 identifiers work the same on Vercel, SoftHSM, and Hardware HSM
- Only the master key storage location changes
- Same HD derivation paths and algorithms
- Public keys remain identical during migration
Implementation Guides
For Initial Deployment: See Vercel Key Management Guide
For SoftHSM Migration: See SoftHSM Migration Guide
For Hardware HSM: See HSM Integration Guide
def get_master_key(self, wallet_version: int) -> bytes:
"""
Retrieve wallet-specific master key from HSM.
Args:
wallet_version: Wallet version identifier (1, 2, 3, etc.)
Returns:
Master key bytes for cryptographic operations
Raises:
HSMKeyNotFoundError: If wallet key doesn't exist
HSMAccessError: If HSM is unavailable
"""
key_id = f"plings_master_key_v{wallet_version}"
try:
# Try primary HSM first
return self.primary_hsm.get_key(key_id)
except HSMKeyNotFoundError:
logger.warning(f"Key {key_id} not found in primary HSM, trying backup")
return self.backup_hsm.get_key(key_id)
except HSMAccessError as e:
logger.error(f"Primary HSM unavailable: {e}, failing over to backup")
return self.backup_hsm.get_key(key_id)
def create_new_wallet(self, reason: str = "security_upgrade",
environment: str = "production") -> int:
"""
Generate new wallet version with fresh master key.
Args:
reason: Reason for new wallet ("key_compromise", "security_upgrade", etc.)
environment: Target environment ("production", "testing", "development")
Returns:
New wallet version ID
"""
# Get next available wallet version
new_version = self._get_next_wallet_version()
key_id = f"plings_master_key_v{new_version}"
# Generate master key in both HSMs
master_key_metadata = {
"key_type": "ed25519",
"extractable": False,
"key_usage": ["derive", "sign"],
"backup_required": True
}
# Create in primary HSM
primary_key = self.primary_hsm.generate_key(key_id, master_key_metadata)
# Create backup in secondary HSM
backup_key = self.backup_hsm.generate_key(key_id, master_key_metadata)
# Verify keys match (if extractable for verification)
if not self._verify_key_consistency(primary_key, backup_key):
raise HSMKeyConsistencyError("Primary and backup keys don't match")
# Register new wallet version in database
self._register_wallet_version(
version_id=new_version,
key_id=key_id,
reason=reason,
environment=environment
)
logger.info(f"✅ Created new wallet v{new_version} for {reason}")
return new_version
def derive_wallet_key(self, wallet_version: int, derivation_path: str) -> bytes:
"""
Derive child key from wallet master key using BIP32.
Args:
wallet_version: Wallet version to derive from
derivation_path: BIP32 path (e.g., "m/44'/501'/1'/2'/1'/3'/158'")
Returns:
Derived key bytes
"""
master_key = self.get_master_key(wallet_version)
# Parse derivation path
path_indices = self._parse_derivation_path(derivation_path)
# Perform BIP32 derivation
current_key = master_key
for index in path_indices:
current_key = self._derive_child_key(current_key, index)
return current_key ```
Wallet Lifecycle Management
Wallet Creation Process
class WalletLifecycleManager:
def __init__(self, key_manager: PlingsKeyManager):
self.key_manager = key_manager
self.db = DatabaseManager()
def create_production_wallet(self, reason: str) -> Dict[str, Any]:
"""Create new production wallet with full security protocols."""
# 1. Generate new wallet with HSM keys
new_wallet_id = self.key_manager.create_new_wallet(
reason=reason,
environment="production"
)
# 2. Initialize Plings as manufacturer #1
plings_manufacturer = self.db.create_manufacturer(
wallet_version=new_wallet_id,
manufacturer_index=1,
name="Plings",
status="active"
)
# 3. Set up basic path allocations
basic_paths = [
("1.1", "generic_tags", "Plings generic tags"),
("1.2", "test_batches", "Plings test batches"),
("1.3", "manufacturer_batches", "Plings manufacturer batches")
]
for path, alloc_type, purpose in basic_paths:
self.db.allocate_path(
wallet_version=new_wallet_id,
path=path,
allocation_type=alloc_type,
purpose=purpose
)
# 4. Update wallet status and default if needed
if reason == "key_compromise":
self._handle_key_compromise_transition(new_wallet_id)
logger.info(f"✅ Production wallet v{new_wallet_id} ready")
return {
"wallet_version": new_wallet_id,
"version_name": f"v{new_wallet_id}",
"manufacturer_count": 1,
"initial_paths": len(basic_paths)
}
def create_development_wallet(self, description: str) -> Dict[str, Any]:
"""Create development wallet for testing."""
dev_wallet_id = self.key_manager.create_new_wallet(
reason="development_environment",
environment="development"
)
# Initialize with test manufacturers
test_manufacturers = [
(1, "Plings"),
(10, "Test Manufacturer A"),
(11, "Test Manufacturer B"),
(12, "Load Test Manufacturer")
]
for index, name in test_manufacturers:
self.db.create_manufacturer(
wallet_version=dev_wallet_id,
manufacturer_index=index,
name=name,
status="active"
)
logger.info(f"✅ Development wallet v{dev_wallet_id} ready")
return {
"wallet_version": dev_wallet_id,
"version_name": f"v{dev_wallet_id}",
"environment": "development",
"manufacturer_count": len(test_manufacturers)
}
URL Format and Backward Compatibility
URL Parameter Strategy
Current URLs (Wallet v1 - Default)
# Default wallet (v1) - no wallet parameter needed
https://s.plings.io?t=q&i=<instance>&p=1.1.1
https://s.plings.io?t=q&p=2.3.2.9j&cp=4K7mX9abDcE&i=<solana_address>
https://s.plings.io?t=q&p=2.3.4.5Q&cp=3K7mX9abDcE&i=<solana_address>
Legacy Identifier Resolution
def resolve_identifier_url(instance_key: str, path: str) -> Dict[str, Any]:
"""
Resolve identifier with intelligent wallet detection.
Resolution Priority:
1. Cryptographic verification against all active wallets
2. Default wallet for new identifier generation
3. Multi-wallet search for legacy identifier migration
"""
# Try default wallet first (fastest path for new identifiers)
default_wallet = get_default_wallet_version()
result = verify_identifier(instance_key, path, default_wallet)
if result["valid"]:
return result
# Fall back to multi-wallet search for legacy identifiers
logger.info(f"Identifier not found in default wallet, searching all active wallets")
for wallet_id in get_active_wallet_versions():
if wallet_id == default_wallet:
continue # Already tried
result = verify_identifier(instance_key, path, wallet_id)
if result["valid"]:
logger.info(f"Legacy identifier found in wallet v{wallet_id}")
return {
**result,
"legacy_identifier": True,
"detected_wallet": f"v{wallet_id}",
"current_url": f"https://s.plings.io?t=q&i={instance_key}&p={path}"
}
return {"valid": False, "reason": "Identifier not found in any active wallet"}
Security Model
Multi-Wallet Threat Analysis
Threat: Key Compromise
Impact: Single wallet compromised, others remain secure Mitigation:
- Immediate wallet retirement
- Automated new wallet creation
- Manufacturer migration protocols
- Grace period for legacy identifier support
Threat: HSM Failure
Impact: Loss of access to specific wallet keys Mitigation:
- Redundant HSM infrastructure
- Cross-region key backups
- Automatic failover protocols
- Emergency key recovery procedures
Threat: Database Compromise
Impact: Wallet metadata exposed, but not private keys Mitigation:
- Keys remain secure in HSM
- Wallet version obfuscation
- Database encryption at rest
- Audit logging for all wallet operations
Progressive Security Evolution
Phase 1: Plings-Managed (Current)
class PlingsmanagedSecurity:
"""
All keys stored in Plings HSM infrastructure.
Organizations trust Plings for key management.
"""
def generate_manufacturer_key(self, manufacturer_name: str,
wallet_version: int) -> Dict[str, str]:
"""Generate manufacturer key within Plings HSM."""
master_key = self.key_manager.get_master_key(wallet_version)
manufacturer_index = self.get_manufacturer_index(manufacturer_name, wallet_version)
# Derive manufacturer key
derivation_path = f"m/44'/501'/{wallet_version}'/{manufacturer_index}'"
manufacturer_key = derive_key(master_key, derivation_path)
# Store public key for verification
public_key = get_public_key(manufacturer_key)
self.db.update_manufacturer_public_key(
wallet_version, manufacturer_index, public_key
)
return {
"manufacturer_key": manufacturer_key, # Private - stays in HSM
"public_key": public_key, # Public - stored in database
"derivation_path": derivation_path
}
Phase 2: Hybrid Management (Planned)
class HybridSecurity:
"""
Organizations can provide their own public keys for verification.
Private keys can be in Plings HSM or organization's control.
"""
def register_organization_key(self, manufacturer_name: str,
organization_public_key: str,
key_source: str) -> Dict[str, str]:
"""Register organization-provided public key."""
# Validate public key format
if not self.validate_ed25519_public_key(organization_public_key):
raise InvalidPublicKeyError("Invalid Ed25519 public key format")
# Store in manufacturer registry
self.db.update_manufacturer(
manufacturer_name=manufacturer_name,
public_key=organization_public_key,
key_delegation_level="verification",
key_source=key_source # "organization_hsm", "organization_managed", "plings_hsm"
)
return {
"verification_method": "organization_public_key",
"key_delegation_level": "verification",
"public_key": organization_public_key
}
Phase 3: Full Delegation (Future)
class FullDelegation:
"""
Organizations control their hardened derivation path.
Provide verification APIs to Plings ecosystem.
Payment routing maintained through Plings PDAs.
"""
def register_organization_delegation(self, manufacturer_name: str,
verification_endpoint: str,
pda_delegation_key: str) -> Dict[str, str]:
"""Register fully delegated organization verification."""
# Validate verification endpoint
if not self.validate_verification_endpoint(verification_endpoint):
raise InvalidEndpointError("Verification endpoint validation failed")
# Test verification capability
test_result = self.test_organization_verification(verification_endpoint)
if not test_result["success"]:
raise VerificationTestFailure("Organization verification test failed")
# Register delegation
self.db.update_manufacturer(
manufacturer_name=manufacturer_name,
verification_endpoint=verification_endpoint,
pda_delegation_key=pda_delegation_key,
key_delegation_level="full"
)
return {
"verification_method": "organization_api",
"key_delegation_level": "full",
"verification_endpoint": verification_endpoint,
"pda_delegation_active": True
}
Operational Procedures
Wallet Monitoring and Alerts
Health Check System
class WalletMonitoring:
def __init__(self):
self.alert_manager = AlertManager()
self.metrics = MetricsCollector()
def monitor_wallet_health(self) -> Dict[str, Any]:
"""Comprehensive wallet health monitoring."""
health_report = {
"timestamp": datetime.utcnow(),
"wallets": {},
"overall_status": "healthy",
"alerts": []
}
for wallet in get_all_wallets():
wallet_health = self._check_wallet_health(wallet)
health_report["wallets"][wallet.version_name] = wallet_health
# Generate alerts for critical issues
if wallet_health["status"] == "critical":
self.alert_manager.send_alert(
severity="critical",
message=f"Wallet {wallet.version_name} health critical",
details=wallet_health
)
return health_report
def _check_wallet_health(self, wallet: WalletVersion) -> Dict[str, Any]:
"""Check individual wallet health metrics."""
health = {
"wallet_version": wallet.version_name,
"status": "healthy",
"issues": [],
"metrics": {}
}
# Check HSM key accessibility
try:
key_accessible = self.key_manager.test_key_access(wallet.version_id)
health["metrics"]["hsm_key_accessible"] = key_accessible
if not key_accessible:
health["issues"].append("HSM key not accessible")
health["status"] = "critical"
except Exception as e:
health["issues"].append(f"HSM error: {str(e)}")
health["status"] = "critical"
# Check identifier generation rate
generation_rate = self.metrics.get_identifier_generation_rate(wallet.version_id)
health["metrics"]["daily_identifiers"] = generation_rate
# Check verification success rate
verification_rate = self.metrics.get_verification_success_rate(wallet.version_id)
health["metrics"]["verification_success_rate"] = verification_rate
if verification_rate < 0.95: # Less than 95% success rate
health["issues"].append("Low verification success rate")
health["status"] = "warning"
# Check manufacturer count
manufacturer_count = self.db.count_active_manufacturers(wallet.version_id)
health["metrics"]["active_manufacturers"] = manufacturer_count
return health
Key Compromise Response Protocol
Automated Incident Response
class IncidentResponse:
def __init__(self):
self.key_manager = PlingsKeyManager()
self.notification_service = NotificationService()
self.audit_logger = AuditLogger()
def handle_key_compromise(self, wallet_version: int,
evidence: Dict[str, Any],
reporter: str) -> Dict[str, Any]:
"""
Execute automated key compromise response protocol.
Steps:
1. Immediately mark wallet as compromised
2. Create new wallet version
3. Update default wallet
4. Notify all stakeholders
5. Begin manufacturer migration process
"""
# Log incident
incident_id = self.audit_logger.log_security_incident(
incident_type="key_compromise",
wallet_version=wallet_version,
evidence=evidence,
reporter=reporter
)
try:
# 1. Mark wallet as compromised
self.db.update_wallet_status(
version_id=wallet_version,
status="compromised",
compromised_at=datetime.utcnow()
)
# 2. Create new wallet version
new_wallet_id = self.key_manager.create_new_wallet(
reason="key_compromise",
environment="production"
)
# 3. Update default wallet
self.db.set_default_wallet(new_wallet_id)
# 4. Migrate Plings to new wallet immediately
self._migrate_plings_to_new_wallet(new_wallet_id)
# 5. Notify all stakeholders
self.notification_service.send_security_alert(
incident_id=incident_id,
wallet_compromised=wallet_version,
new_wallet=new_wallet_id,
immediate_actions_required=True
)
# 6. Schedule manufacturer migrations
migration_plan = self._create_migration_plan(wallet_version, new_wallet_id)
self.audit_logger.log_incident_response(
incident_id=incident_id,
actions_taken=[
"wallet_marked_compromised",
"new_wallet_created",
"default_wallet_updated",
"plings_migrated",
"stakeholders_notified"
],
new_wallet_version=new_wallet_id
)
return {
"incident_id": incident_id,
"compromised_wallet": f"v{wallet_version}",
"new_wallet": f"v{new_wallet_id}",
"migration_plan": migration_plan,
"status": "incident_response_complete"
}
except Exception as e:
self.audit_logger.log_incident_response_failure(
incident_id=incident_id,
error=str(e)
)
# Send emergency notification
self.notification_service.send_emergency_alert(
message="Key compromise response failed",
incident_id=incident_id,
error=str(e)
)
raise
Implementation Roadmap
Phase 1: Core Wallet Infrastructure (2 weeks)
- ✅ Database schema updates
- ✅ Wallet registry implementation
- ✅ Basic HSM integration
- ✅ Wallet-aware identifier generation
Phase 2: Migration & Security (2 weeks)
- 🔄 Key compromise response protocols
- 🔄 Manufacturer migration workflows
- 🔄 Multi-wallet verification system
- 🔄 Operational monitoring tools
Phase 3: Advanced Features (3 weeks)
- 🔲 Development environment wallets
- 🔲 Organization key delegation (Phase 2 security model)
- 🔲 Automated wallet health monitoring
- 🔲 Performance optimization for multi-wallet operations
Phase 4: Full Delegation Preparation (Future)
- 🔲 Organization verification API framework
- 🔲 PDA delegation protocols
- 🔲 Full key delegation support
- 🔲 Distributed key management tools
Benefits Summary
Security Benefits
- Isolated key compromise impact: Only affected wallet compromised, others remain secure
- Rapid incident response: Automated protocols for key compromise scenarios
- Progressive security evolution: Smooth transition from centralized to distributed key management
- HSM integration: Hardware-level security for all master keys
Operational Benefits
- Multi-environment support: Separate wallets for development, testing, production
- Clean migrations: Logical manufacturer namespaces maintained across wallet versions
- Monitoring & alerting: Comprehensive health monitoring for all wallet operations
- Audit trails: Complete traceability of all wallet and key management operations
Scalability Benefits
- Unlimited wallet versions: No architectural limits on wallet creation
- Manufacturer isolation: Manufacturers can operate independently within wallet namespaces
- Performance optimization: Wallet-specific caching and optimization strategies
- Global distribution: Wallet-specific geographic distribution for compliance
This wallet-first architecture provides the foundation for secure, scalable, and operationally robust HD wallet management while maintaining the simplicity and elegance needed for global adoption.
Wallet-Aware Path Registry Implementation
Path Allocation with Wallet Context
The path registry system is deeply integrated with the wallet architecture, ensuring cryptographic security and namespace isolation for each manufacturer.
Path Allocation Ranges by Wallet
| Wallet | Manufacturer | Range | Purpose | Example Paths | Management |
|---|---|---|---|---|---|
| v1 | Plings (1) | 2.2.*.x |
Generic Tags | 2.2.2.2.2, 2.2.2.3.2 + class pointers |
Plings Internal |
| v1 | Plings (1) | 2.3.*.x |
Test Batches | 2.3.2.2.2, 2.3.2.5.2 + class pointers |
Plings Internal |
| v1 | IKEA (2) | 2.*.*.x |
Furniture/Bikes | 2.3.2.7P.9j + class pointer 4K7mX9abDcE |
IKEA |
| v1 | Coca-Cola (3) | 2.*.*.x |
Classic Products | 2.3j.4.5Q.3L8z + class pointer 3K7mX9abDcE |
Coca-Cola |
| v2 | All | Same patterns | Secondary production | Production paths | Same manufacturers |
| v3 | Dev/Test | 2.B.*.*.x, B.2.*.*.x |
Development | 2.B.2.2.2, B.2.2.2 + class pointers |
Plings Dev |
Wallet-Aware Path Allocation Process
def allocate_path_in_wallet(wallet_version: int, allocation_type: str,
quantity: int, **kwargs) -> Dict[str, Any]:
"""
Allocate path in specific wallet version.
Args:
wallet_version: Target wallet (1, 2, 3, etc.)
allocation_type: Type of allocation
quantity: Number of identifiers needed
**kwargs: Additional parameters
Returns:
Allocation details with wallet-specific derivation
"""
# Get manufacturer index within this wallet
manufacturer_name = kwargs.get('manufacturer_name', 'Plings')
manufacturer_index = get_manufacturer_index_in_wallet(wallet_version, manufacturer_name)
if not manufacturer_index:
# Auto-register manufacturer in new wallet if transferring
if kwargs.get('source_wallet'):
manufacturer_index = transfer_manufacturer_to_wallet(
manufacturer_name,
source_wallet=kwargs['source_wallet'],
target_wallet=wallet_version
)
else:
raise ValueError(f"Manufacturer {manufacturer_name} not registered in wallet v{wallet_version}")
# Build wallet-aware path
if allocation_type == "generic":
base_path = f"{manufacturer_index}.1"
elif allocation_type == "test":
base_path = f"{manufacturer_index}.2"
elif allocation_type == "manufacturer_batch":
base_path = f"{manufacturer_index}.3"
elif allocation_type == "development":
base_path = f"{manufacturer_index}.10" # Development paths use 10+ range
else:
raise ValueError(f"Unknown allocation type: {allocation_type}")
# Find next available index within this wallet
max_index = get_max_index_for_wallet_path(wallet_version, base_path)
new_path = f"{base_path}.{max_index + 1}"
# Generate wallet-aware HD derivation
hd_derivation = path_to_wallet_hd_derivation(new_path, wallet_version)
# Register allocation
allocation_id = register_wallet_path_allocation(
wallet_version=wallet_version,
path=new_path,
hd_derivation=hd_derivation,
allocation_type=allocation_type,
quantity=quantity,
**kwargs
)
return {
"allocation_id": allocation_id,
"wallet_version": wallet_version,
"path": new_path,
"hd_derivation": hd_derivation,
"manufacturer_index": manufacturer_index,
"url_format": f"https://s.plings.io?t=q&i=&p={new_path}",
"transfer_capable": True
}
Path-to-HD-Derivation Conversion
The wallet system converts business-friendly paths to cryptographic HD derivations:
def path_to_wallet_hd_derivation(path: str, wallet_version: int) -> str:
"""
Convert path to wallet-aware HD derivation.
Args:
path: Object path (e.g., "2.3.2.7P.9j") with separate class pointer
wallet_version: Wallet version (1, 2, 3, etc.)
Returns:
Wallet-aware HD derivation (e.g., "m/44'/501'/1'/2'/1'/3'/2024'/158'")
"""
parts = path.split('.')
# Start with Solana standard + wallet version (hardened)
derivation = f"m/44'/501'/{wallet_version}'"
# Manufacturer level is hardened (anchor point)
manufacturer_index = parts[0]
derivation += f"/{manufacturer_index}'"
# Process remaining parts (class information handled separately via class pointer)
for part in parts[1:]:
# All path segments are regular indices, no special markers
derivation += f"/{part}'"
return derivation
Multi-Wallet Path Verification
When verifying identifiers, the system searches across all active wallets:
def resolve_identifier_with_wallet_detection(instance_key: str, path: str) -> Dict[str, Any]:
"""
Resolve identifier with intelligent wallet detection.
Resolution Priority:
1. Cryptographic verification against all active wallets
2. Default wallet for new identifier generation
3. Multi-wallet search for legacy identifier migration
"""
# Try default wallet first (fastest path for new identifiers)
default_wallet = get_default_wallet_version()
result = verify_identifier_in_wallet(instance_key, path, default_wallet)
if result["valid"]:
return {
**result,
"wallet_version": default_wallet,
"is_default_wallet": True
}
# Fall back to multi-wallet search for legacy identifiers
logger.info(f"Identifier not found in default wallet v{default_wallet}, searching all active wallets")
for wallet_id in get_active_wallet_versions():
if wallet_id == default_wallet:
continue # Already tried
result = verify_identifier_in_wallet(instance_key, path, wallet_id)
if result["valid"]:
logger.info(f"Legacy identifier found in wallet v{wallet_id}")
return {
**result,
"wallet_version": wallet_id,
"legacy_identifier": True,
"recommended_url": f"https://s.plings.io?t=q&i={instance_key}&p={path}",
"migration_available": can_migrate_to_default_wallet(wallet_id)
}
return {
"valid": False,
"reason": "Identifier not found in any active wallet",
"searched_wallets": get_active_wallet_versions()
}
Manufacturer Transfer Between Wallets
When migrating manufacturers between wallet versions:
def transfer_manufacturer_to_new_wallet(manufacturer_name: str,
source_wallet: int,
target_wallet: int,
transfer_reason: str) -> Dict[str, Any]:
"""
Transfer manufacturer from source wallet to target wallet.
This preserves the manufacturer's path allocations while moving
them to a new cryptographic namespace.
"""
# Get original manufacturer details
original_manufacturer = get_manufacturer_in_wallet(source_wallet, manufacturer_name)
if not original_manufacturer:
raise ValueError(f"Manufacturer {manufacturer_name} not found in wallet v{source_wallet}")
# Preserve manufacturer index for logical consistency
new_manufacturer_index = original_manufacturer.manufacturer_index
# Check if index is available in target wallet
if is_manufacturer_index_taken(target_wallet, new_manufacturer_index):
# Find next available index if original is taken
new_manufacturer_index = get_next_available_manufacturer_index(target_wallet)
# Create manufacturer in target wallet
new_manufacturer_id = create_manufacturer_in_wallet(
wallet_version=target_wallet,
manufacturer_index=new_manufacturer_index,
manufacturer_name=manufacturer_name,
organization_id=original_manufacturer.organization_id,
status="active",
transferred_from_wallet=source_wallet,
transfer_reason=transfer_reason
)
# Update manufacturer lineage tracking
update_manufacturer_lineage(
canonical_name=manufacturer_name,
current_wallet_version=target_wallet,
current_manufacturer_index=new_manufacturer_index,
predecessor_wallet=source_wallet,
predecessor_index=original_manufacturer.manufacturer_index,
assignment_reason=transfer_reason
)
logger.info(f"✅ Transferred {manufacturer_name} from wallet v{source_wallet} to v{target_wallet}")
return {
"manufacturer_name": manufacturer_name,
"source_wallet": source_wallet,
"target_wallet": target_wallet,
"new_manufacturer_index": new_manufacturer_index,
"transfer_reason": transfer_reason,
"status": "transfer_complete"
}
Related Documentation
- Path Registry System - Business-focused guide to the path system
- Wallet Lifecycle Management - Operational procedures for wallet management
- Wallet Security Model - Security architecture and threat model
- Key Compromise Procedures - Incident response protocols
- Plings Identifier System - How identifiers work with wallets
Documentation Status: Core architecture complete
Next Phase: Implementation of key compromise response protocols
Review Required: Security team review of HSM integration design