feat: add gitea agentic runtime control plane
This commit is contained in:
43
engine/devops_agent/policies.py
Normal file
43
engine/devops_agent/policies.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
class PolicyViolation(PermissionError):
|
||||
"""Raised when runtime behavior violates declared workflow policy."""
|
||||
|
||||
|
||||
def _normalize_path(path: str) -> str:
|
||||
return path.replace("\\", "/").lstrip("./")
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class RuntimePolicy:
|
||||
safe_outputs: dict[str, dict[str, int | str | bool]]
|
||||
path_scope: list[str]
|
||||
_operation_counts: dict[str, int] = field(default_factory=dict)
|
||||
|
||||
def assert_operation_allowed(self, action: str) -> None:
|
||||
config = self.safe_outputs.get(action)
|
||||
if config is None:
|
||||
raise PolicyViolation(f"write action '{action}' is not declared in safe_outputs")
|
||||
|
||||
current_count = self._operation_counts.get(action, 0) + 1
|
||||
max_count = int(config.get("max", current_count))
|
||||
if current_count > max_count:
|
||||
raise PolicyViolation(f"write action '{action}' exceeded max count {max_count}")
|
||||
|
||||
self._operation_counts[action] = current_count
|
||||
|
||||
def assert_path_allowed(self, path: str) -> None:
|
||||
normalized = _normalize_path(path)
|
||||
if not self.path_scope:
|
||||
raise PolicyViolation("file writes are not allowed without an explicit path scope")
|
||||
|
||||
for allowed_prefix in self.path_scope:
|
||||
if normalized.startswith(_normalize_path(allowed_prefix)):
|
||||
return
|
||||
|
||||
raise PolicyViolation(
|
||||
f"path '{normalized}' is outside allowed path scope {self.path_scope}"
|
||||
)
|
||||
Reference in New Issue
Block a user