When should a role be global?
Ordinary roles are scoped to a service. When several services share a role assignment, define the assignment in the specially named global service and use that role in each service’s own authorization policies.
Only global role policies are supported. A global role assignment does not itself grant every operation; each ordinary service still defines its permissions. Global authorization policies are not supported.
Before running the examples
Build ./bin/spctl, ./bin/speedle-pms and ./bin/speedle-ads using the quick start. Use Go 1.26.10 or Go 1.27.3 (or a newer patch on the same release branch), Bash, curl and Python 3. Run each terminal from the repository root. Use a fresh policy file for this page; reset it only after stopping both services.
Initialize an empty policy file:
printf '{}\n' > docs-policies.jsonIn terminal one, start PMS and leave it running:
./bin/speedle-pms --store-type file --filestore-loc ./docs-policies.json --endpoint 127.0.0.1:6733 --grpc-endpoint 127.0.0.1:0 --insecure=trueIn terminal two, start ADS and leave it running:
./bin/speedle-ads --store-type file --filestore-loc ./docs-policies.json --endpoint 127.0.0.1:6734 --grpc-endpoint 127.0.0.1:0 --insecure=trueRun the remaining commands in a third terminal. PMS and ADS share the file; watch propagates changes asynchronously. Confirm the intended update has reached ADS before relying on it. --insecure=true is only for this loopback example; see security for production connections. Explicit PMS addresses avoid changing ~/.spctlconfig. Stop both server terminals with Ctrl-C when finished.
Create a global role and a local permission
./bin/spctl --pms-endpoint http://127.0.0.1:6733/policy-mgmt/v1/ create service global
./bin/spctl --pms-endpoint http://127.0.0.1:6733/policy-mgmt/v1/ create rolepolicy -c "grant user Emma AdminRole" --service-name global
./bin/spctl --pms-endpoint http://127.0.0.1:6733/policy-mgmt/v1/ create service library
./bin/spctl --pms-endpoint http://127.0.0.1:6733/policy-mgmt/v1/ create policy -c "grant role AdminRole borrow books" --service-name libraryglobal must use exactly that service name. library is created before its policy. Both are managed through normal service APIs.
Check the result
Emma is allowed through AdminRole; Bob is denied.
curl --fail --silent --show-error -H 'Content-Type: application/json' \
-d '{"subject":{"principals":[{"type":"user","name":"Emma"}]},"serviceName":"library","resource":"books","action":"borrow"}' \
http://127.0.0.1:6734/authz-check/v1/is-allowedcurl --fail --silent --show-error -H 'Content-Type: application/json' \
-d '{"subject":{"principals":[{"type":"user","name":"Bob"}]},"serviceName":"library","resource":"books","action":"borrow"}' \
http://127.0.0.1:6734/authz-check/v1/is-allowedA resource-scoped global role policy applies only to its resource scope. Keep cross-service role assignments under review, especially when identities span different domains.