From 18c09a1237cca839851c12fbda26741ea5e28911 Mon Sep 17 00:00:00 2001 From: Yao Lu Date: Fri, 3 Jul 2026 22:47:19 -0700 Subject: [PATCH] fix(lumilake): accept lum.id's lumid:admin scope as an admin bypass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PermissionPolicy admin_scopes ({lumilake:*, flowmesh:admin, ...}) never included lum.id's actual platform-admin scope, lumid:admin. lum.id super_admin/admin PATs carry lumid:read/write/admin (+ flowmesh:workflows:write) from /oauth/introspect — none of which matched, so the kind-level lumilake:jobs:write gate rejected EVERY real caller and job submission was impossible for any lum.id token. Add lumid:admin (mirrors the flowmesh:admin rationale for shared platform admins). Verified end-to-end in the UKS deployment (job submit 403 -> 422). Co-Authored-By: Claude Opus 4.8 (1M context) --- src/lumid_lumilake_plugin/permissions.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lumid_lumilake_plugin/permissions.py b/src/lumid_lumilake_plugin/permissions.py index d565b79..3654cc1 100644 --- a/src/lumid_lumilake_plugin/permissions.py +++ b/src/lumid_lumilake_plugin/permissions.py @@ -15,7 +15,12 @@ from ._core import GrantLevel, GrantStore, PermissionChecker, PermissionPolicy _POLICY = PermissionPolicy( - admin_scopes=frozenset({"*", "lumilake:*", "lumilake:admin", "flowmesh:admin"}), + # `lumid:admin` is lum.id's platform-admin scope (what super_admin/admin PATs actually carry + # from /oauth/introspect). Included so lum.id platform admins get Lumilake admin without needing + # a Lumilake-specific scope — mirrors the `flowmesh:admin` rationale. Without it NO lum.id token + # (not even super_admin, which carries lumid:read/write/admin) could pass the kind-level + # `lumilake:jobs:write` gate, so job submission was impossible for every real caller. + admin_scopes=frozenset({"*", "lumilake:*", "lumilake:admin", "flowmesh:admin", "lumid:admin"}), # Anything not in this map is admin-only at kind level. kind_level_scopes={ (ResourceKind.JOB.value, ResourceAction.READ.value): "lumilake:jobs:read",