Permissions and roles

State Usergroup Rules

Permissions and roles

State Usergroup Rules has no module-specific privilege. Its admin API routes sit in the same privilege group as vendor management, so access follows the vendor privileges.

Privileges in play

PrivilegeGrants
view_vendorsRead the rule list (GET /api/v1/admin/state-usergroup-rules).
manage_vendorsEverything in view_vendors, plus create/upsert (POST) and delete (DELETE).
manage_modules or manage_settingsTurn the module on or off at /admin/modules.

There is no manage_state_rules privilege today. Tenants that need a stricter audit surface should grant manage_vendors only to a small admin team.

Typical role mapping

RoleWhat they should be able to doPrivileges to grant
Platform adminEverythingall privileges
Finance opsRead rules to debug pricing issuesview_vendors
MarketingDefine which states go to which campaign groupmanage_vendors (broad, but it's the lever the routes use)
Customer supportLook up which group a user got assigned touser read access — they read /admin/users/<id>
VendorNo access(vendors don't see this page at all)

Vendor isolation

Vendors do NOT see this page. State Usergroup Rules is platform-level — the rules are tenant-wide, not per-vendor. A marketplace running multiple vendors shares one rule set; per-vendor regional segmentation must be done at the catalog level rather than via this module.

Page-level gating

The admin page /admin/state-usergroup-rules is gated by:

  1. Module enabled? Disabled module → the API returns 403 module_disabled and the page shows "module not enabled".
  2. Admin signed in? Signed-out → redirect to the admin login.
  3. Privileges — view_vendors for reads, manage_vendors for writes. The backend checks on every request; hiding buttons in the UI is not a security boundary.

Runtime auto-assign privilege

The rule fires from users.Service.ApplyStateUsergroups regardless of who triggered the address write. That means:

  • A customer saving their own address → fires.
  • An admin creating an address on the customer's behalf → fires.
  • A script creating addresses through the API → fires (the service is called per address).

There is no per-actor permission gate inside ApplyStateUsergroups. The assumption is that anyone authorised to write an address row is implicitly authorised to fire the rule.

Audit trail

Every assignment writes a log line. There is no DB audit table for state usergroup decisions specifically — if you need a paper trail beyond the log, query usergroup_links filtered by the rule's target group and cross-reference with the customer's address changes. Imperfect; a dedicated audit log is on the roadmap.

Multi-tenant boundary

Rules are stored in the tenant database. One tenant's CA → wholesale-ca rule does not leak into another tenant's data. The runtime check IsEnabled(tenant, "state-usergroup-rules") re-confirms the tenant before any read, so a misconfigured request that lands on the wrong tenant still gets gated.