Admin authorization - #566
Merged
MaryammAli merged 3 commits intoAug 23, 2026
Merged
Conversation
MaryammAli
approved these changes
Aug 23, 2026
MaryammAli
left a comment
Contributor
There was a problem hiding this comment.
LGTM
Keep up the good work dev....
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.
All tasks complete. Here's a summary of what was implemented:
Summary of Changes
Problem
Admin authorization boundaries were loose — governance-level operations (emergency mode, upgrades) were accessible to anyone with the Admin role, and hook registration had no authorization at all. The require_any_role function also redundantly validated admin state for non-admin role checks.
Changes Made
Added Role::Governance = 4 for protocol-changing decisions (emergency mode, upgrades)
Documented it as strictly higher-privilege than Admin for auditability
2. admin.rs — Tightened authorization logic
Fixed require_any_role: Removed the redundant current_admin() call that unnecessarily validated admin role state for non-admin role checks (e.g., Operator)
Added require_governance(): New function requiring the Governance role specifically
Gated start_upgrade, upgrade, cancel_upgrade: Changed from require_admin to require_governance
complete_upgrade: Governance is enforced at start_upgrade entry; migrate() re-checks admin access internally (avoids Soroban double-auth)
Added doc comments clarifying role requirements on set_paused
3. lib.rs — Authorization boundaries and documentation
activate_emergency_mode: Changed from require_admin to require_governance
register_hook / unregister_hook: Added require_admin guard (previously had only guard_initialized)
set_upgrade_gate: Changed from require_admin to require_governance
Updated access model table: Now documents all 6 privilege tiers (Governance → Admin → Operator → Owner → Arbiter → Public)
Updated docs on start_upgrade, cancel_upgrade, complete_upgrade, upgrade, migrate
4. test_context.rs — New with_governance() constructor
Grants both Admin + Governance roles for tests needing full governance authority
5. role_test.rs — 16 new security boundary tests
Governance role grant/revoke
Emergency mode requires Governance role (rejects Admin-only)
start_upgrade requires Governance role (rejects Admin-only)
cancel_upgrade requires Governance role
set_upgrade_gate requires Governance role
Operator cannot activate emergency mode or start upgrades
Admin-only actions still work for Admin
Admin cannot perform governance actions without Governance role
Unauthorized user blocked from all privileged operations
register_hook/unregister_hook require Admin role
Corrupt admin role state still blocks operations
6. guard_test.rs — 6 new governance guard tests
Emergency mode rejects Admin without Governance role
Emergency mode accepted with Governance role
start_upgrade rejects Admin without Governance
set_upgrade_gate rejects Admin without Governance
register_hook rejects unauthorized / accepts Admin
7. README.md — Documented governance boundaries
Added three-tier role table (Governance → Admin → Operator)
Listed key invariants for the authorization model
8. Existing test fixes (metadata_test, test.rs, upgrade_test) — All upgraded to use Governance role where needed
Verification
428 unit tests pass, 0 failures
No breaking changes to existing test patterns (all pre-existing tests adapted)
I'll propose some follow-up directions now.
▸
Worked · 1 step
The implementation is complete. All 428 tests pass with 0 failures across all affected files.
Here's what was done:
Core authorization tightening:
Added Role::Governance (level 4) to types.rs — separates protocol-changing decisions from routine admin
Added require_governance() in admin.rs — explicit check for governance-only paths
Fixed require_any_role — removed stale current_admin() validation that wasn't checking the caller's roles directly
Gated start_upgrade, upgrade, cancel_upgrade, set_upgrade_gate, activate_emergency_mode behind require_governance
Added require_admin to register_hook / unregister_hook (previously no auth check beyond init)
Governance isolation:
Upgrade lifecycle (start_upgrade → upgrade → complete_upgrade) requires Governance role
Emergency mode activation requires Governance role (irreversible state)
complete_upgrade avoids double-auth by relying on start_upgrade having already gated and migrate() re-checking admin internally
Test coverage:
16 new security boundary tests in role_test.rs covering admin, governance, operator, and unauthorized paths
6 new guard tests in guard_test.rs validating governance-specific guard behavior
Updated all 34 pre-existing failing tests to use the new governance-aware TestContext::with_governance()
All 428 tests pass cleanly
closes #561