Wire the role Resolver and feed granted permissions into policy evaluation
Related to gitlab-org/gitlab#600048
What
Two related steps toward role-based authorization in GLAZ:
- Wire the
Resolver(glaz-roles) — turn the set of roles a subject holds into an effective permission set. - Feed that set into policy evaluation (
glaz-policy) — so the Cedar decision is driven by the permissions the subject actually holds, not a hardcoded value.
Changes
glaz-roles — Resolver
- Role-id-keyed in-memory index:
load/get, pluspermissions(role_ids)(the deduplicated union of those roles' permissions) andhas_permission(role_ids, perm). - Removed the dead access-level
levelconstants (the old access-level-keyed design they belonged to is gone) and tidied the Resolver docs/test names for the flat role model.
glaz-policy — granted-driven decision
PolicyEngine::checkgainsgranted_permissions: &[Permission].user_permissionsis built from it and is authoritative over any value the caller puts incontext.- Previously
user_permissionswas hardcoded to the single requested action, which made the sharedpermit_role_grantedpolicy a tautology (every request "held" exactly the permission it asked about). Now the grant is actually consulted. - The engine stays a pure Cedar evaluator — it does not know which roles a subject holds. Callers resolve
granted_permissions(e.g. viaResolver::permissions()).
glaz-module
- Decodes the merged
CheckRequestcontract and passes a documented placeholdergranted_permissions(the requested action) for now — it does not yet resolve the subject's roles from the request'srelationships.
Tests
cargo test --workspace — all passing. Notably:
- A request whose action is not in
granted_permissionsis denied (proves the grant is consulted, no longer a tautology). - A
granted_permissionsset resolved from a role viaResolver::permissions()drives the decision (allow for a granted action, deny for one outside the role's permissions).
Notes / follow-ups
- Built on the merged AR
↔️ GLAZ contract (!28 (merged)). Rebased ontomain;glaz-moduledecodes theCheck/CheckRequestcontract (Principalsubject,object,relationships,context). Thechecksignature also reconciles with the explicit schema/policy-initialization work onmain(it carries bothgranted_permissionsand theNotInitializedbehavior). glaz-moduleis a placeholder, not end-to-end yet. With the placeholdergranted_permissions, the module-level check effectively always allows; the value here is theResolver+glaz-policyplumbing.- Next (#600048): compute effective permissions from the request's
relationships— resolve role grants → union via theResolver→ evaluate — plus an action-validity gate and the org-owner bypass. The schema-from-roles question is resolved there (Rust validity gate + schema-less Cedar), not here.
Edited by Diane Russel