Files
ai-contract-platform/backend/tools/formal_launch_governance_cli.py
T

121 lines
3.9 KiB
Python

import argparse
import json
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Formal launch governance database helper")
parser.add_argument("command", choices=["import", "snapshot"])
parser.add_argument("--database-url", default=None)
parser.add_argument("--bootstrap-mode", choices=["none", "sqlite_governance"], default="none")
parser.add_argument("--tenant-id", default="tenant-demo-001")
parser.add_argument("--user-id", default=None)
parser.add_argument("--username", default="admin@example.com")
parser.add_argument("--display-name", default="治理导入脚本")
parser.add_argument("--batch-name", default=None)
return parser.parse_args()
def configure_env(database_url: str | None) -> None:
if database_url:
os.environ["DATABASE_URL"] = database_url
def bootstrap_sqlite_governance() -> None:
from sqlalchemy import create_engine
from app.db import Base
from app.models.governance_asset import GovernanceAsset
from app.models.governance_evidence import GovernanceEvidence
from app.models.governance_gate_run import GovernanceGateRun
from app.models.governance_release_batch import GovernanceReleaseBatch
from app.models.governance_review_assignment import GovernanceReviewAssignment
from app.models.governance_review_decision import GovernanceReviewDecision
database_url = os.environ["DATABASE_URL"]
engine = create_engine(database_url, future=True)
try:
Base.metadata.create_all(
engine,
tables=[
GovernanceAsset.__table__,
GovernanceReviewAssignment.__table__,
GovernanceReviewDecision.__table__,
GovernanceEvidence.__table__,
GovernanceReleaseBatch.__table__,
GovernanceGateRun.__table__,
],
)
finally:
engine.dispose()
def build_current_user(args: argparse.Namespace) -> dict:
return {
"id": args.user_id,
"tenant_id": args.tenant_id,
"role": "admin",
"display_name": args.display_name,
"username": args.username,
}
def run_command(args: argparse.Namespace) -> dict:
if args.bootstrap_mode == "sqlite_governance":
bootstrap_sqlite_governance()
from app.db import SessionLocal
from app.services.governance_service import GovernanceService
session = SessionLocal()
try:
service = GovernanceService(session)
current_user = build_current_user(args)
if args.command == "import":
data = service.import_formal_launch(current_user, batch_name=args.batch_name)
status = "PASS"
else:
data = service.get_formal_launch_database_snapshot(current_user)
status = data.get("status", "BLOCKED")
return {
"status": status,
"command": args.command,
"generated_at": datetime.now(timezone.utc).isoformat(),
"tenant_id": args.tenant_id,
"data": data,
}
finally:
session.close()
def main() -> int:
args = parse_args()
configure_env(args.database_url)
repo_backend_root = Path(__file__).resolve().parents[1]
if str(repo_backend_root) not in sys.path:
sys.path.insert(0, str(repo_backend_root))
try:
payload = run_command(args)
except Exception as exc: # noqa: BLE001
payload = {
"status": "FAIL",
"command": args.command,
"generated_at": datetime.now(timezone.utc).isoformat(),
"tenant_id": args.tenant_id,
"error": str(exc),
}
print(json.dumps(payload, ensure_ascii=False))
return 1
print(json.dumps(payload, ensure_ascii=False))
return 0 if payload["status"] != "FAIL" else 1
if __name__ == "__main__":
raise SystemExit(main())