nothingworry's picture
feat: Add LLM rule explanations, real-time visualizations, and fix analytics permissions
adf80ee
raw
history blame
2.15 kB
from __future__ import annotations
from typing import Optional, Set
# Role hierarchy used across MCP server and FastAPI routes
VALID_ROLES = ("viewer", "editor", "admin", "owner")
ROLE_ORDER = {role: idx for idx, role in enumerate(VALID_ROLES)}
# Permission matrix defining which roles can perform which enterprise actions
PERMISSIONS: dict[str, Set[str]] = {
"manage_rules": {"owner", "admin"},
"ingest_documents": {"owner", "admin", "editor"},
"delete_documents": {"owner", "admin"},
"view_analytics": {"viewer", "editor", "admin", "owner"}, # All roles can view analytics
}
# Mapping of MCP tool names to enterprise actions
TOOL_PERMISSION_MAP: dict[str, str] = {
"admin.addRule": "manage_rules",
"admin.deleteRule": "manage_rules",
"rag.ingest": "ingest_documents",
"rag.delete": "delete_documents",
}
def normalize_role(raw_value: Optional[str]) -> str:
"""
Normalize an inbound role string. Defaults to 'viewer' when undefined or invalid.
"""
if not raw_value:
return "viewer"
value = raw_value.strip().lower()
if value not in VALID_ROLES:
return "viewer"
return value
def allowed_roles_for(action: str) -> Set[str]:
"""
Return the set of roles that can execute the given action.
If the action is unknown, all roles are allowed.
"""
return PERMISSIONS.get(action, set(VALID_ROLES))
def role_allows(role: str, action: str) -> bool:
"""
Check whether the supplied role has permission for the action.
Unknown actions default to allow-all to avoid accidental lockouts.
"""
allowed = allowed_roles_for(action)
return role in allowed if allowed else True
def describe_allowed_roles(action: str) -> str:
"""
Return a human-friendly description of which roles are allowed for an action.
"""
allowed = sorted(allowed_roles_for(action), key=lambda r: ROLE_ORDER.get(r, 0))
return ", ".join(allowed)
def get_required_action_for_tool(tool_name: str) -> Optional[str]:
"""
Look up the enterprise action that applies to a tool name, if any.
"""
return TOOL_PERMISSION_MAP.get(tool_name)