fix: dedup migration queue to prevent unbounded memory growth
the migration queue had no dedup — unlike the resolve queue which uses
queued_set. every message from a DID with a host mismatch would dupe
the DID string from c_allocator and append to the queue. with thousands
of mismatched DIDs producing messages faster than the 4 resolver threads
could drain, the queue + duped strings grew without bound (~430 MiB/hr).
- add migration_pending set to dedup migration queue entries
- on confirmed migration: remove from pending (allow re-evaluation)
- on rejected migration: leave in pending (suppress re-queueing)
- evictKey (#identity events) clears pending for that DID
- add relay_validator_migration_pending prometheus metric
- convert validator cache and DID cache to proper LRU (from lru.zig)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>