mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
281 lines
7.0 KiB
Python
281 lines
7.0 KiB
Python
"""
|
|
Permission Models
|
|
|
|
Data classes and enums for permission management.
|
|
"""
|
|
|
|
from dataclasses import dataclass
|
|
from enum import IntEnum
|
|
from uuid import UUID
|
|
|
|
from roboco.agents_config import ROLE_PERMISSION_LEVELS
|
|
from roboco.models import AgentRole, Team
|
|
|
|
|
|
class PermissionLevel(IntEnum):
|
|
"""Hierarchical permission levels."""
|
|
|
|
CEO = 0 # Full access
|
|
BOARD = 1 # Cross-org access
|
|
MAIN_PM = 2 # All cells access
|
|
CELL_PM = 3 # Own cell + PM channel
|
|
CELL_MEMBER = 4 # Own cell only
|
|
AUDITOR = 99 # Special: silent read all
|
|
|
|
|
|
# Build ROLE_LEVELS from agents_config (single source of truth)
|
|
def _build_role_levels() -> dict[AgentRole, PermissionLevel]:
|
|
"""Build role-to-level mapping from agents_config."""
|
|
mapping: dict[AgentRole, PermissionLevel] = {}
|
|
for role_str, level_str in ROLE_PERMISSION_LEVELS.items():
|
|
try:
|
|
role = AgentRole(role_str)
|
|
level = PermissionLevel[level_str]
|
|
mapping[role] = level
|
|
except (ValueError, KeyError):
|
|
pass
|
|
return mapping
|
|
|
|
|
|
ROLE_LEVELS: dict[AgentRole, PermissionLevel] = _build_role_levels()
|
|
|
|
|
|
class TaskAction:
|
|
"""Task actions that require permission."""
|
|
|
|
VIEW_ALL = "view_all"
|
|
VIEW_OWN = "view_own"
|
|
CREATE = "create"
|
|
ASSIGN = "assign"
|
|
CLAIM = "claim"
|
|
UPDATE_OWN = "update_own"
|
|
CLOSE = "close"
|
|
CHANGE_PRIORITY = "change_priority"
|
|
|
|
|
|
class KBAction:
|
|
"""Knowledge base actions that require permission."""
|
|
|
|
INDEX_CODE = "index_code"
|
|
INDEX_DOCS = "index_docs"
|
|
SEARCH = "search"
|
|
QUERY = "query"
|
|
VIEW_STATS = "view_stats"
|
|
CLEAR_INDEX = "clear_index"
|
|
REFRESH_INDEX = "refresh_index"
|
|
|
|
|
|
@dataclass
|
|
class AgentContext:
|
|
"""Context for permission checks."""
|
|
|
|
agent_id: UUID
|
|
role: AgentRole
|
|
team: Team | None = None
|
|
slug: str | None = None # Agent slug (e.g., "be-dev-1")
|
|
|
|
@property
|
|
def level(self) -> PermissionLevel:
|
|
return ROLE_LEVELS.get(self.role, PermissionLevel.CELL_MEMBER)
|
|
|
|
|
|
# Defines who can directly communicate with whom
|
|
COMMUNICATION_MATRIX: dict[AgentRole, set[AgentRole]] = {
|
|
# CEO can communicate with everyone
|
|
AgentRole.CEO: set(AgentRole),
|
|
# Board members
|
|
AgentRole.PRODUCT_OWNER: {
|
|
AgentRole.CEO,
|
|
AgentRole.HEAD_MARKETING,
|
|
AgentRole.AUDITOR,
|
|
AgentRole.MAIN_PM,
|
|
},
|
|
AgentRole.HEAD_MARKETING: {
|
|
AgentRole.CEO,
|
|
AgentRole.PRODUCT_OWNER,
|
|
AgentRole.AUDITOR,
|
|
AgentRole.MAIN_PM,
|
|
},
|
|
# Auditor can communicate with everyone
|
|
AgentRole.AUDITOR: set(AgentRole),
|
|
# Main PM
|
|
AgentRole.MAIN_PM: {
|
|
AgentRole.CEO,
|
|
AgentRole.PRODUCT_OWNER,
|
|
AgentRole.HEAD_MARKETING,
|
|
AgentRole.AUDITOR,
|
|
AgentRole.CELL_PM,
|
|
},
|
|
# Cell PM communicates with their cell and other PMs
|
|
AgentRole.CELL_PM: {
|
|
AgentRole.CEO,
|
|
AgentRole.AUDITOR,
|
|
AgentRole.MAIN_PM,
|
|
AgentRole.CELL_PM,
|
|
AgentRole.DEVELOPER,
|
|
AgentRole.QA,
|
|
AgentRole.DOCUMENTER,
|
|
},
|
|
# Cell members communicate within cell
|
|
AgentRole.DEVELOPER: {
|
|
AgentRole.CEO,
|
|
AgentRole.AUDITOR,
|
|
AgentRole.CELL_PM,
|
|
AgentRole.DEVELOPER,
|
|
AgentRole.QA,
|
|
AgentRole.DOCUMENTER,
|
|
},
|
|
AgentRole.QA: {
|
|
AgentRole.CEO,
|
|
AgentRole.AUDITOR,
|
|
AgentRole.CELL_PM,
|
|
AgentRole.DEVELOPER,
|
|
AgentRole.QA,
|
|
AgentRole.DOCUMENTER,
|
|
},
|
|
AgentRole.DOCUMENTER: {
|
|
AgentRole.CEO,
|
|
AgentRole.AUDITOR,
|
|
AgentRole.CELL_PM,
|
|
AgentRole.DEVELOPER,
|
|
AgentRole.QA,
|
|
AgentRole.DOCUMENTER,
|
|
},
|
|
}
|
|
|
|
|
|
TASK_PERMISSIONS: dict[AgentRole, set[str]] = {
|
|
# System role (orchestrator) has full access for internal operations
|
|
AgentRole.SYSTEM: {
|
|
TaskAction.VIEW_ALL,
|
|
TaskAction.CREATE,
|
|
TaskAction.ASSIGN,
|
|
TaskAction.CLAIM,
|
|
TaskAction.UPDATE_OWN,
|
|
TaskAction.CLOSE,
|
|
TaskAction.CHANGE_PRIORITY,
|
|
},
|
|
AgentRole.CEO: {
|
|
TaskAction.VIEW_ALL,
|
|
TaskAction.CREATE,
|
|
TaskAction.ASSIGN,
|
|
TaskAction.CLOSE,
|
|
TaskAction.CHANGE_PRIORITY,
|
|
},
|
|
AgentRole.PRODUCT_OWNER: {
|
|
TaskAction.VIEW_ALL,
|
|
TaskAction.CREATE,
|
|
TaskAction.ASSIGN,
|
|
TaskAction.CLOSE,
|
|
TaskAction.CHANGE_PRIORITY,
|
|
},
|
|
AgentRole.HEAD_MARKETING: {
|
|
TaskAction.VIEW_ALL,
|
|
TaskAction.CREATE,
|
|
TaskAction.ASSIGN,
|
|
TaskAction.CLOSE,
|
|
TaskAction.CHANGE_PRIORITY,
|
|
},
|
|
AgentRole.AUDITOR: {
|
|
TaskAction.VIEW_ALL,
|
|
TaskAction.CREATE,
|
|
TaskAction.ASSIGN,
|
|
TaskAction.CLOSE,
|
|
TaskAction.CHANGE_PRIORITY,
|
|
},
|
|
AgentRole.MAIN_PM: {
|
|
TaskAction.VIEW_ALL,
|
|
TaskAction.CREATE,
|
|
TaskAction.ASSIGN,
|
|
TaskAction.CLAIM, # Required to assign tasks via claim endpoint
|
|
TaskAction.CLOSE,
|
|
TaskAction.CHANGE_PRIORITY,
|
|
},
|
|
AgentRole.CELL_PM: {
|
|
TaskAction.VIEW_OWN, # Own cell only
|
|
TaskAction.CREATE,
|
|
TaskAction.ASSIGN,
|
|
TaskAction.CLAIM, # Required to assign tasks via claim endpoint
|
|
TaskAction.CLOSE,
|
|
TaskAction.CHANGE_PRIORITY,
|
|
},
|
|
AgentRole.DEVELOPER: {
|
|
TaskAction.VIEW_OWN,
|
|
TaskAction.CLAIM,
|
|
TaskAction.UPDATE_OWN,
|
|
TaskAction.CLOSE, # Can close own tasks
|
|
},
|
|
AgentRole.QA: {
|
|
TaskAction.VIEW_OWN,
|
|
TaskAction.CLAIM,
|
|
TaskAction.UPDATE_OWN,
|
|
},
|
|
AgentRole.DOCUMENTER: {
|
|
TaskAction.VIEW_OWN,
|
|
TaskAction.CLAIM,
|
|
TaskAction.UPDATE_OWN,
|
|
TaskAction.CLOSE, # Documenters complete tasks after documentation
|
|
},
|
|
}
|
|
|
|
|
|
# Knowledge Base permissions - defines who can perform KB operations
|
|
KB_PERMISSIONS: dict[AgentRole, set[str]] = {
|
|
AgentRole.CEO: {
|
|
KBAction.INDEX_CODE,
|
|
KBAction.INDEX_DOCS,
|
|
KBAction.SEARCH,
|
|
KBAction.QUERY,
|
|
KBAction.VIEW_STATS,
|
|
KBAction.CLEAR_INDEX,
|
|
KBAction.REFRESH_INDEX,
|
|
},
|
|
AgentRole.PRODUCT_OWNER: {
|
|
KBAction.INDEX_DOCS,
|
|
KBAction.SEARCH,
|
|
KBAction.QUERY,
|
|
KBAction.VIEW_STATS,
|
|
},
|
|
AgentRole.HEAD_MARKETING: {
|
|
KBAction.INDEX_DOCS,
|
|
KBAction.SEARCH,
|
|
KBAction.QUERY,
|
|
},
|
|
AgentRole.AUDITOR: {
|
|
KBAction.SEARCH,
|
|
KBAction.QUERY,
|
|
KBAction.VIEW_STATS,
|
|
},
|
|
AgentRole.MAIN_PM: {
|
|
KBAction.INDEX_CODE,
|
|
KBAction.INDEX_DOCS,
|
|
KBAction.SEARCH,
|
|
KBAction.QUERY,
|
|
KBAction.VIEW_STATS,
|
|
KBAction.CLEAR_INDEX,
|
|
KBAction.REFRESH_INDEX,
|
|
},
|
|
AgentRole.CELL_PM: {
|
|
KBAction.INDEX_CODE,
|
|
KBAction.INDEX_DOCS,
|
|
KBAction.SEARCH,
|
|
KBAction.QUERY,
|
|
KBAction.VIEW_STATS,
|
|
},
|
|
AgentRole.DEVELOPER: {
|
|
KBAction.INDEX_CODE,
|
|
KBAction.INDEX_DOCS,
|
|
KBAction.SEARCH,
|
|
KBAction.QUERY,
|
|
},
|
|
AgentRole.QA: {
|
|
KBAction.SEARCH,
|
|
KBAction.QUERY,
|
|
},
|
|
AgentRole.DOCUMENTER: {
|
|
KBAction.INDEX_DOCS,
|
|
KBAction.SEARCH,
|
|
KBAction.QUERY,
|
|
},
|
|
}
|