policy.py 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. from __future__ import annotations
  2. from typing import Any
  3. from app.core.orchestration.models import PolicyDecision
  4. from app.core.orchestration.spec import (
  5. validate_schedule_plan,
  6. validate_workflow_spec,
  7. )
  8. ENVIRONMENTS = {"development", "test", "production"}
  9. def evaluate_candidate(
  10. workflow_spec: Any,
  11. schedule_plan: Any,
  12. *,
  13. environment: str,
  14. deploy_disabled: bool,
  15. canary_required: bool,
  16. ) -> PolicyDecision:
  17. workflow = validate_workflow_spec(workflow_spec)
  18. validate_schedule_plan(schedule_plan)
  19. if environment not in ENVIRONMENTS:
  20. raise ValueError("unsupported environment")
  21. has_write = any(
  22. node["type"] == "sql.execute" or node.get("purpose") == "write"
  23. for node in workflow["nodes"]
  24. )
  25. risk = "high" if has_write else ("medium" if environment == "production" else "low")
  26. reasons = []
  27. if environment == "production" and not deploy_disabled:
  28. reasons.append("production candidate must deploy disabled")
  29. if environment == "production" and has_write and not canary_required:
  30. reasons.append("production write candidate requires canary")
  31. return PolicyDecision(
  32. allowed=not reasons,
  33. risk=risk,
  34. reasons=tuple(reasons),
  35. )