profit 77655c298c Initial commit: Agent Governance System Phase 8
Phase 8 Production Hardening with complete governance infrastructure:

- Vault integration with tiered policies (T0-T4)
- DragonflyDB state management
- SQLite audit ledger
- Pipeline DSL and templates
- Promotion/revocation engine
- Checkpoint system for session persistence
- Health manager and circuit breaker for fault tolerance
- GitHub/Slack integrations
- Architectural test pipeline with bug watcher, suggestion engine, council review
- Multi-agent chaos testing framework

Test Results:
- Governance tests: 68/68 passing
- E2E workflow: 16/16 passing
- Phase 2 Vault: 14/14 passing
- Integration tests: 27/27 passing

Coverage: 57.6% average across 12 phases

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 22:07:06 -05:00

256 lines
9.6 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Unified Preflight System
========================
Combines all preflight checks into a single gate.
Part of Phase 3: Execution Pipeline - Preflight System.
This is the main entry point for preflight validation.
All execution must pass through this gate.
"""
import json
import sys
from dataclasses import dataclass
from datetime import datetime, timezone
from typing import Optional
from inventory_check import InventoryChecker
from dependency_check import DependencyChecker
from sandbox_assert import SandboxAsserter, AssertionStatus
@dataclass
class PreflightGate:
"""
Unified preflight gate that blocks execution on any failure.
Gate Order:
1. Sandbox Assertion (CRITICAL - must pass first)
2. Inventory Validation
3. Dependency Check
If any check fails, execution is BLOCKED.
"""
def __init__(self):
self.inventory_checker = InventoryChecker()
self.dependency_checker = DependencyChecker()
self.sandbox_asserter = SandboxAsserter()
def _now(self) -> str:
return datetime.now(timezone.utc).isoformat()
def run_preflight(
self,
targets: list[str],
action_type: str,
agent_tier: int,
agent_id: str,
extra_secrets: list[str] = None,
allow_staging: bool = False,
production_override: bool = False
) -> dict:
"""
Run full preflight validation.
Args:
targets: List of target nodes
action_type: Type of action (terraform, ansible, docker, generic)
agent_tier: Agent's trust tier (0-4)
agent_id: Agent identifier for audit
extra_secrets: Additional secrets to validate
allow_staging: Allow staging targets
production_override: DANGEROUS: Allow production
Returns:
Comprehensive preflight report with gate decision
"""
start_time = datetime.now(timezone.utc)
report = {
"report_type": "unified_preflight",
"agent_id": agent_id,
"agent_tier": agent_tier,
"action_type": action_type,
"targets": targets,
"timestamp": self._now(),
"gates": {},
"gate_order": ["sandbox", "inventory", "dependencies"],
"failed_gates": [],
"can_proceed": True,
"decision": "PENDING",
"blocking_reason": None
}
# =====================================================================
# GATE 1: Sandbox Assertion (CRITICAL)
# =====================================================================
print("\n[GATE 1/3] Sandbox Assertion...")
sandbox_report = self.sandbox_asserter.assert_all_targets(
targets,
allow_staging=allow_staging,
production_override=production_override
)
report["gates"]["sandbox"] = sandbox_report
if not sandbox_report["can_proceed"]:
report["can_proceed"] = False
report["failed_gates"].append("sandbox")
report["decision"] = "BLOCKED"
report["blocking_reason"] = f"Sandbox assertion failed: {sandbox_report['blocked_targets']}"
print(f" [BLOCKED] Sandbox assertion failed")
# Short-circuit: Don't run other checks if sandbox fails
report["duration_ms"] = int((datetime.now(timezone.utc) - start_time).total_seconds() * 1000)
return report
else:
print(f" [PASS] All targets within sandbox boundaries")
# =====================================================================
# GATE 2: Inventory Validation
# =====================================================================
print("\n[GATE 2/3] Inventory Validation...")
inventory_report = self.inventory_checker.preflight_report(targets, agent_tier)
report["gates"]["inventory"] = inventory_report
if not inventory_report["can_proceed"]:
report["can_proceed"] = False
report["failed_gates"].append("inventory")
if report["decision"] == "PENDING":
report["decision"] = "BLOCKED"
report["blocking_reason"] = f"Inventory validation failed"
print(f" [BLOCKED] Inventory validation failed")
else:
print(f" [PASS] All targets validated in inventory")
# =====================================================================
# GATE 3: Dependency Check
# =====================================================================
print("\n[GATE 3/3] Dependency Check...")
dependency_report = self.dependency_checker.preflight_report(action_type, extra_secrets)
report["gates"]["dependencies"] = dependency_report
if not dependency_report["can_proceed"]:
report["can_proceed"] = False
report["failed_gates"].append("dependencies")
if report["decision"] == "PENDING":
report["decision"] = "BLOCKED"
report["blocking_reason"] = f"Dependency check failed"
print(f" [BLOCKED] Dependency check failed")
else:
print(f" [PASS] All dependencies available")
# =====================================================================
# Final Decision
# =====================================================================
if report["can_proceed"]:
report["decision"] = "APPROVED"
report["blocking_reason"] = None
report["duration_ms"] = int((datetime.now(timezone.utc) - start_time).total_seconds() * 1000)
return report
def print_report(self, report: dict):
"""Print a human-readable report"""
print("\n" + "=" * 70)
print("UNIFIED PREFLIGHT REPORT")
print("=" * 70)
print(f"Agent ID: {report['agent_id']}")
print(f"Agent Tier: {report['agent_tier']}")
print(f"Action Type: {report['action_type']}")
print(f"Targets: {report['targets']}")
print(f"Timestamp: {report['timestamp']}")
print(f"Duration: {report['duration_ms']}ms")
print()
print("GATE RESULTS:")
print("-" * 70)
for gate_name in report["gate_order"]:
gate = report["gates"].get(gate_name, {})
passed = gate.get("can_proceed", False)
status = "[PASS]" if passed else "[FAIL]"
print(f" {status} {gate_name.upper()}")
if gate_name == "sandbox":
summary = gate.get("summary", {})
print(f" Safe: {summary.get('safe', 0)}, Unsafe: {summary.get('unsafe', 0)}, Risk: {summary.get('max_risk_level', 0)}/4")
elif gate_name == "inventory":
summary = gate.get("summary", {})
print(f" Checks: {summary.get('total_checks', 0)}, Passed: {summary.get('passed', 0)}, Failed: {summary.get('failed', 0)}")
elif gate_name == "dependencies":
summary = gate.get("summary", {})
print(f" Checks: {summary.get('total_checks', 0)}, Passed: {summary.get('passed', 0)}, Failed: {summary.get('failed', 0)}")
print()
print("-" * 70)
print("DECISION")
print("-" * 70)
if report["can_proceed"]:
print(f" [APPROVED] Preflight checks passed - execution authorized")
else:
print(f" [BLOCKED] Preflight checks failed - execution denied")
print(f" Failed Gates: {report['failed_gates']}")
print(f" Reason: {report['blocking_reason']}")
print("=" * 70)
# =============================================================================
# CLI
# =============================================================================
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description="Unified Preflight Gate")
parser.add_argument("targets", nargs="+", help="Target nodes")
parser.add_argument("--action", "-a", default="generic",
choices=["terraform", "ansible", "docker", "generic"],
help="Action type")
parser.add_argument("--tier", "-t", type=int, default=1, help="Agent tier (0-4)")
parser.add_argument("--agent-id", default="cli-user", help="Agent identifier")
parser.add_argument("--secret", action="append", dest="extra_secrets",
help="Additional secrets to check")
parser.add_argument("--allow-staging", action="store_true",
help="Allow staging targets")
parser.add_argument("--production-override", action="store_true",
help="DANGEROUS: Allow production targets")
parser.add_argument("--json", action="store_true", help="Output JSON only")
parser.add_argument("--quiet", "-q", action="store_true", help="Quiet mode")
args = parser.parse_args()
gate = PreflightGate()
if not args.quiet:
print(f"\n{'='*70}")
print("PREFLIGHT CHECK INITIATED")
print(f"{'='*70}")
print(f"Agent: {args.agent_id} (Tier {args.tier})")
print(f"Action: {args.action}")
print(f"Targets: {args.targets}")
report = gate.run_preflight(
targets=args.targets,
action_type=args.action,
agent_tier=args.tier,
agent_id=args.agent_id,
extra_secrets=args.extra_secrets,
allow_staging=args.allow_staging,
production_override=args.production_override
)
if args.json:
print(json.dumps(report, indent=2))
elif not args.quiet:
gate.print_report(report)
sys.exit(0 if report["can_proceed"] else 1)