Summary
The current delegate migration system uses a LEGACY_DELEGATES array that manually tracks old delegate keys. This works but requires manual maintenance and bypasses the delegate encapsulation model.
Problem
When delegate WASM changes (due to dependency updates, bug fixes, etc.), the delegate key changes because key = BLAKE3(BLAKE3(WASM) || params). The current workaround:
- Hard-code old delegate keys in
LEGACY_DELEGATES array
- Check if the current delegate matches any legacy key
- If so, migrate data from old delegate to new one
This approach:
- Requires manual maintenance every time delegate WASM changes
- Creates a growing list of legacy keys to track
- Bypasses the delegate trust model (any code could claim to be a "legacy" delegate)
- Risk of forgetting to add old keys, breaking migration for users
Proposed Solution: Signed Delegate Chains
Implement a proper delegate migration system using cryptographic signatures:
- Each delegate version is signed by the application's signing key
- Delegates only reveal private keys (room secrets, signing keys) to another delegate that:
- Has a valid signature from the same application key
- Presents a proper migration request
- Chain of trust: New delegate proves it's authorized by presenting its signed certificate
- No manual key tracking: The delegate itself verifies the migration chain
Design Sketch
DelegateMigrationRequest {
source_delegate_key: DelegateKey, // Old delegate
target_delegate_key: DelegateKey, // New delegate
target_code_signature: Signature, // App key signs new WASM hash
migration_token: MigrationToken, // One-time use token
}
The old delegate validates:
target_code_signature is valid for the target WASM hash
- The signing key matches the expected application key
- The migration token is fresh (prevent replay)
Then transfers its secrets to the new delegate.
Benefits
- Eliminates
LEGACY_DELEGATES array entirely
- Preserves delegate encapsulation and trust model
- Automatic migration without manual key tracking
- Replay-protected via one-time tokens
- Works across arbitrary version jumps (not just N to N+1)
Current Workaround
The LEGACY_DELEGATES approach in chat_delegate.rs works for now but should be replaced with this proper solution.
Related
- Room contract migration is handled separately via
OptionalUpgradeV1 upgrade pointers
- This issue specifically covers delegate-level migration (where secrets are stored)
[AI-assisted - Claude]
Summary
The current delegate migration system uses a
LEGACY_DELEGATESarray that manually tracks old delegate keys. This works but requires manual maintenance and bypasses the delegate encapsulation model.Problem
When delegate WASM changes (due to dependency updates, bug fixes, etc.), the delegate key changes because
key = BLAKE3(BLAKE3(WASM) || params). The current workaround:LEGACY_DELEGATESarrayThis approach:
Proposed Solution: Signed Delegate Chains
Implement a proper delegate migration system using cryptographic signatures:
Design Sketch
The old delegate validates:
target_code_signatureis valid for the target WASM hashThen transfers its secrets to the new delegate.
Benefits
LEGACY_DELEGATESarray entirelyCurrent Workaround
The
LEGACY_DELEGATESapproach inchat_delegate.rsworks for now but should be replaced with this proper solution.Related
OptionalUpgradeV1upgrade pointers[AI-assisted - Claude]