Skip to content

smartcontract: enforce Permission flags on multicast allowlist and subscribe/create-user handlers#3966

Open
bgm-malbeclabs wants to merge 1 commit into
mainfrom
feature/least-privilege-oracle-access
Open

smartcontract: enforce Permission flags on multicast allowlist and subscribe/create-user handlers#3966
bgm-malbeclabs wants to merge 1 commit into
mainfrom
feature/least-privilege-oracle-access

Conversation

@bgm-malbeclabs

Copy link
Copy Markdown
Contributor

Summary of Changes

  • Continues the Permission-account authorization migration (New Permission series) to the four remaining access-pass / multicast / user handlers the feed oracle calls, so the oracle can operate on an ACCESS_PASS_ADMIN | USER_ADMIN Permission account instead of foundation_allowlist membership. This is the serviceability half (Unit 1) of RFC-2 — least privilege for a hot, always-online key.
  • AddMulticastGroupSubAllowlist / RemoveMulticastGroupSubAllowlist now honor an ACCESS_PASS_ADMIN Permission account, OR'd around the existing multicast-group-owner check. Add switches to split_trailing_permission so the optional user_payer (connect-credit funding) account and the optional trailing Permission account are disambiguated by PDA match rather than a colliding length check.
  • UpdateMulticastGroupRoles: granting roles on another owner's pass is now an ACCESS_PASS_ADMIN operation, while removal-only cleanup stays USER_ADMIN (unchanged from [New Permission 3/5] smartcontract: enforce Permission-based authorization in existing instructions #3206). Splitting by operation preserves the deliberate "USER_ADMIN is removal-only here" contract and its tests, and keeps the historical NotAllowed / Unauthorized error variants exact.
  • CreateSubscribeUser owner-override now accepts a USER_ADMIN Permission holder in addition to the sentinel and foundation. The Permission account is threaded through CreateUserCoreAccounts (None for CreateUser, which never overrides the owner).
  • The Permission path carries no owns-it restriction, so a flag holder acts across owners — required for the validator-owned users and passes the oracle manages. The change is additive: every existing caller keeps its exact current authority.
  • PERMISSION.md: documents domain-instruction enforcement for the access-pass / multicast / user surface, and corrects legacy-mapping rows (USER_ADMIN, ACCESS_PASS_ADMIN, NETWORK_ADMIN, MULTICAST_ADMIN) that were stale after the activator retirement.

Context: RFC-2 (malbeclabs/infra#1764), malbeclabs/doublezero-shreds#517. SetAccessPass, CloseAccessPass, DeleteUser, and the UpdateMulticastGroupRoles removal branch were already Permission-wired by #3206, so this PR completes the set with no new authorization helper — it follows the established authorize() pattern.

Testing Verification

  • Added integration tests exercising the new Permission path for each wired handler, all proving the cross-owner (no owns-it) property:
    • test_multicast_subscriber_allowlist_access_pass_admin_permission — an ACCESS_PASS_ADMIN holder (not owner/foundation/sentinel/feed) adds then removes a subscriber allowlist entry on a pass it does not own.
    • test_subscribe_access_pass_admin_permission_allowed — an ACCESS_PASS_ADMIN holder subscribes a user cross-owner.
    • test_create_subscribe_user_user_admin_owner_override — a USER_ADMIN holder creates a subscribe-user with owner != payer.
  • Preserved the existing [New Permission 3/5] smartcontract: enforce Permission-based authorization in existing instructions #3206 contract tests: test_subscribe_user_admin_permission_rejected (USER_ADMIN still cannot add roles) and test_unsubscribe_user_admin_permission_allowed (USER_ADMIN removal cleanup) both still pass.
  • Full doublezero-serviceability suite green under the host toolchain (cargo test -p doublezero-serviceability); cargo fmt --check and cargo clippy --all-targets clean; cargo build-sbf succeeds.
  • Note: test_set_accesspass_refills_depleted_user_payer is a pre-existing flake on main (airdrop-refill balance assertion, unrelated to authorization) — confirmed it fails intermittently on a clean checkout without these changes.

…bscribe/create-user handlers

Continues the Permission-account authorization migration to the remaining
access-pass/multicast/user handlers the feed oracle calls, so the oracle can
operate on an ACCESS_PASS_ADMIN | USER_ADMIN Permission account instead of
foundation_allowlist membership (least privilege for a hot, always-online key).

- AddMulticastGroupSubAllowlist / RemoveMulticastGroupSubAllowlist honor an
  ACCESS_PASS_ADMIN Permission account, OR'd around the existing
  multicast-group-owner check. Add uses split_trailing_permission to
  disambiguate the optional user_payer account from the trailing Permission
  account.
- UpdateMulticastGroupRoles: granting roles on another owner's pass is now an
  ACCESS_PASS_ADMIN operation; removal-only cleanup stays USER_ADMIN. The
  historical NotAllowed/Unauthorized error variants are preserved.
- CreateSubscribeUser owner-override now accepts a USER_ADMIN Permission holder
  in addition to the sentinel and foundation.
- PERMISSION.md: document domain-instruction enforcement for the access-pass /
  multicast / user surface, and correct legacy-mapping rows that were stale
  after the activator retirement.

The Permission path carries no owns-it restriction, so a flag holder acts across
owners, which the oracle needs for validator-owned users and passes. The change
is additive: every existing caller keeps its current authority.

Refs: RFC-2 (malbeclabs/infra#1764), malbeclabs/doublezero-shreds#517
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant