feat(cli): add riverctl debug member-info raw record dump - #578
Draft
sanity wants to merge 1 commit into
Draft
Conversation
There was no read-only command that exposed per-record member_info version/signature data — `member list` and `debug room-state` both canonicalize via `MemberInfoV1::canonical`, so a duplicate `member_id` (two signed records, possibly at the same version) is invisible by construction. That check is a pre-migration gate for #571 / #572, which changed the equal-version tiebreak from raw signature bytes to a signature digest — a surviving equal-version duplicate could resolve to a different winner under the new rule. `debug member-info <room_owner_key>` dumps the raw member_info vector as fetched over the live node connection, one row per record (member_id, version, signature digest, deputy count), and reports total records, distinct member_ids, any member_id with more than one record, and specifically any equal-version duplicates. Closes #577
Merged
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
There was no read-only command that exposed per-record
member_infodata.
member listanddebug room-stateboth canonicalize viaMemberInfoV1::canonical, so a duplicatemember_id(two signedrecords for the same member, possibly at the same
version) isinvisible by construction.
debug room-stateshows only aggregates(
member_count,ban_count, deputy grants), anddebug contract-getprints a summary, not raw state.
This mattered because #571/#572 changed the equal-version tiebreak in
MemberInfoV1::canonicalfrom comparing raw signature bytes to asignature digest (
SigDigest). A surviving equal-version duplicate inthe live Official room could resolve to a different winner under
the new rule than under the old one — a pre-migration correctness
check with no way to run it against live network state.
Approach
Added
riverctl debug member-info <room_owner_key>, following theexisting
debugsubcommand pattern (debug bans,debug room-state,etc.): fetch the room via
api.get_room(the same live-node pathevery other
debugsubcommand uses — read-only, no local storemutation), then dump
state.member_info.member_info(the RAWVec<AuthorizedMemberInfo>) directly, deliberately bypassingcanonical.Per record:
member_id,version, a hex-encoded signature digest,and deputy count. The digest is the SAME 128-bit BLAKE3 digest
(
blake3(signature.to_bytes()), first 16 bytes) thatMemberInfoV1's privatesig_digestuses as the real equal-versiontiebreak discriminator — recomputed here since that function isn't
pub. A unit test pins it against the same golden vector asriver-core's ownsig_digest_golden_vectortest, so a mismatchbetween the two would fail loudly rather than silently reporting the
wrong discriminator.
The summary reports total records, distinct
member_ids, anymember_idwith more than one record (regardless of version), andspecifically the dangerous subset:
member_ids with two or morerecords at the identical version.
Testing
collect_member_info_dump: no false positive ondistinct members, flags a genuine equal-version duplicate, and does
NOT flag a legitimate version bump (different versions for the same
member) as an equal-version collision.
sig_digest_hexagainst the same fixedinput/output as
river_core'ssig_digest_golden_vector.member_info_command_delegates_to_the_shared_helper)mirroring the existing
bans_command_delegates_to_the_shared_helperspattern in this file — asserts the
executearm callscollect_member_info_dumpand never calls.canonical(.4uNUKFzZQCnzo4K2ecZ16cMsYEEfoaRS35z6exEsbvm4) via a local node'swebsocket API, using a fresh empty
--config-dirso the run isguaranteed read-only (no locally-stored identity for that room means
neither
ensure_room_migratednor the GET-path member_info self-healcan publish anything). Result: 127 total records, 127 distinct
member_ids, 0 duplicates, 0 equal-version duplicates — PASS. Cross-
checked against
debug room-stateon the same node/moment: 126members + 1 owner record = 127, consistent.
Closes #577
[AI-assisted - Claude]