Repository navigation
Conversation
The upgrader does not accept an empty disaster recovery committee, so the station now refuses changes that would leave the committee unset or without active members: - SetDisasterRecovery requires a committee whose user group has an active member, checked at creation and again at execution. - Editing a user, or removing the admin role, fails when it would take the last active member out of the committee. The upgrader's reply to the committee and account syncs is decoded as its result type, so an error reply is reported as a failed sync. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
✅ No security or compliance issues detected. Reviewed everything up to 4854f72. Security OverviewDetected Code Changes
|
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The membership guards and synchronization reply handling match the intended behavior, with regression coverage and no identified blocking issues.
No open issues 🎉
What changed in this PR
This PR prevents station operations from emptying the disaster recovery committee and makes upgrader synchronization failures visible, while preserving installation without a committee.
Changes:
- Validate committee membership when requests are created and executed.
- Block user changes that remove the last active committee member.
- Decode upgrader error replies and add regression tests for committee safeguards.
| File | Description |
|---|---|
tests/integration/src/disaster_recovery_tests.rs |
Tests rejection of requests without a committee. |
core/station/impl/src/services/user.rs |
Guards the last active committee member and tests allowed and rejected edits. |
core/station/impl/src/services/system.rs |
Validates committee changes while preserving initialization behavior. |
core/station/impl/src/services/disaster_recovery.rs |
Propagates upgrader synchronization errors. |
core/station/impl/src/factories/requests/set_disaster_recovery.rs |
Validates requests at creation and execution, with unit tests. |
core/station/impl/src/errors/disaster_recovery.rs |
Adds errors for missing and inactive committees. |
Review effort: Balanced
…hange The upgrader keeps its own copy of each committee member's identities and name. Editing those fields on a user who stays in the committee now triggers a committee sync, so the upgrader's copy matches the station. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This branch has not been deployed
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.
Summary
The station mirrors its disaster recovery committee to the upgrader. The upgrader does not accept an empty committee: it rejects the update and keeps the committee it already has. The station did not account for this, and it decoded the upgrader's reply as
(), so an error reply was treated as a successful sync.This change keeps the station's committee non-empty and in sync with the upgrader, and reports a failed sync:
SetDisasterRecoverynow requires a committee (committee: Noneis refused) whose user group has at least one active member. The check runs when the request is created and again when it executes, so it applies to the state at execution time. The Candid input is unchanged, and installing a station without a committee still works.edit_userrefuses a change that takes the last active member out of the configured committee, either by removing the committee group or by setting the user to inactive.remove_adminapplies the same check when the committee group is the admin group. Changes that do not remove an active member, including edits on a station whose committee already has no active member, are unaffected.DisasterRecoveryErrorvariants:MISSING_COMMITTEEandCOMMITTEE_WITHOUT_ACTIVE_MEMBERS.sync_committeeandsync_accounts_and_assetsdecode the upgrader's reply asApiResultand turn anErrintoCommitteeSyncFailed/AccountSyncFailed.The upgrader and the wallet frontend are unchanged.
Tests
services/user.rsandfactories/requests/set_disaster_recovery.rs. The 7 refusal tests fail with the new checks disabled and pass with them; the 4 tests for changes that stay allowed pass either way.cargo test -p station --lib: 420 passed, 0 failed.cargo fmt --check,cargo clippy -p station --tests -- -D warningsandcargo clippy -p integration-tests --tests -- -D warningspass.test_set_disaster_recovery_requires_committee: aSetDisasterRecoveryrequest without a committee is rejected with a validation error and the upgrader's committee is unchanged.test_committee_member_identity_change_is_synced: after a committee member's identity is changed from A to B, the upgrader's committee lists B and not A, a disaster recovery request from A is rejected and one from B is accepted. It fails with the new sync condition disabled and passes with it../scripts/run-integration-tests.sh: thedisaster_recoveryfilter passed 14 of 14 on the first commit, and the new identity test passed on the second commit.🤖 Generated with Claude Code