Skip to content

feat: Implement signed delegate chain migration #123

@sanity

Description

@sanity

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:

  1. Hard-code old delegate keys in LEGACY_DELEGATES array
  2. Check if the current delegate matches any legacy key
  3. 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:

  1. Each delegate version is signed by the application's signing key
  2. 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
  3. Chain of trust: New delegate proves it's authorized by presenting its signed certificate
  4. 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]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions