QueryQuest / src /queryquest /core /policy.py
mohamedgamal04
QueryQuest — Hugging Face Spaces deploy (Docker)
0cac9cf
Raw
History Blame Contribute Delete
1.99 kB
"""Approval policies that decide whether the engine may execute or write back.
The engine never prompts on its own. It asks a Policy. The CLI supplies an
interactive policy (asks the human); the future autonomous website supplies
`AutoApprovePolicy`. Keeping this rich-free means `core` has no CLI dependency.
Author: mohamedgamal04
"""
from __future__ import annotations
from abc import ABC, abstractmethod
from pathlib import Path
from .models import StatementResult, WritebackTarget
class Policy(ABC):
"""Decision points the engine consults instead of prompting directly."""
@abstractmethod
async def approve_execution(self, statements: list[StatementResult]) -> bool:
"""Return True to run the validated statements."""
@abstractmethod
async def approve_writeback(self, target: WritebackTarget) -> bool:
"""Return True to persist this DML target back to its workbook."""
class AutoApprovePolicy(Policy):
"""No-human policy for autonomous use; still confines writes to excel_dir."""
def __init__(self, excel_dir: str | Path | None) -> None:
self._excel_dir = Path(excel_dir).resolve() if excel_dir is not None else None
async def approve_execution(self, statements: list[StatementResult]) -> bool:
return True
async def approve_writeback(self, target: WritebackTarget) -> bool:
# Defense in depth: even with no human, never write outside the workbook
# directory the engine was pointed at.
if self._excel_dir is None:
return True
resolved = target.file_path.resolve()
return self._excel_dir == resolved or self._excel_dir in resolved.parents
class DenyAllPolicy(Policy):
"""Dry-run policy: generate and validate, but never execute or persist."""
async def approve_execution(self, statements: list[StatementResult]) -> bool:
return False
async def approve_writeback(self, target: WritebackTarget) -> bool:
return False