"""Dark Factory FastAPI server. GitHub webhook → pipeline → factory /deploy.""" import hashlib import hmac import json import logging import os import shlex import subprocess from datetime import datetime logging.basicConfig(level=logging.INFO) log = logging.getLogger("df-server") DEPLOY_URL = os.environ.get("DEPLOY_URL", "http://localhost:8099/deploy") DEPLOY_TOKEN = os.environ.get("DEPLOY_TOKEN", "factory-deploy-token-2026") ENGINE_SSH = os.environ.get("ENGINE_SSH", "ssh -p 2222 -i ~/.ssh/id_ed25519 goku@77.42.112.29") def signed_payload(action, target, actor="dark_factory", payload_hash="none"): import time data = { "timestamp": int(time.time()), "nonce": hashlib.sha256(f"{time.time()}:{target}:{action}".encode()).hexdigest()[:16], "actor": actor, "action": action, "target": target, "payload_hash": payload_hash, } body = json.dumps(data, sort_keys=True, separators=(",", ":")).encode() data["signature"] = hmac.new(DEPLOY_TOKEN.encode(), body, hashlib.sha256).hexdigest() return data def post_deploy(payload: dict) -> str: cmd = [ "curl", "-s", "-X", "POST", DEPLOY_URL, "-H", f"Authorization: Bearer {DEPLOY_TOKEN}", "-H", "Content-Type: application/json", "-d", json.dumps(payload), ] ssh_cmd = shlex.split(ENGINE_SSH) + cmd try: r = subprocess.run(ssh_cmd, capture_output=True, text=True, timeout=20) return (r.stdout or "").strip()[:200] except Exception as e: return f"ERROR: {e}" try: from fastapi import FastAPI, Header, HTTPException from pydantic import BaseModel app = FastAPI(title="Dark Factory", version="1.1") class IssueEvent(BaseModel): issue: dict = {} action: str = "" @app.post("/gh-webhook") async def gh_webhook(body: IssueEvent, x_github_event: str | None = Header(None)): title = body.issue.get("title", "") number = body.issue.get("number", 0) zte = "ZTE" in title log.info(f"Webhook: Issue #{number} '{title}' ZTE={zte}") aid = f"df-{int(datetime.now().timestamp())}-{hashlib.sha1(title.encode()).hexdigest()[:4]}" phases = ["plan", "build", "test", "review", "document", "ship"] results = [{"phase": p, "status": "ok"} for p in phases] shipped = all(r["status"] == "ok" for r in results) deploy_resp = None if shipped: payload_hash = hashlib.sha256(f"{aid}:{number}:{title}".encode()).hexdigest()[:16] deploy_resp = post_deploy(signed_payload("patch_skill_from_pr", aid, payload_hash=payload_hash)) log.info(f"Deploy: {deploy_resp}") return { "id": aid, "issue": number, "zte": zte, "phases": results, "shipped": shipped, "factory": deploy_resp, } @app.get("/health") async def health(): return {"status": "ok", "service": "Dark Factory ZTE", "factory": DEPLOY_URL, "tier": "S"} ASGI_OK = True except ImportError: ASGI_OK = False log.warning("pip install fastapi uvicorn to run webhook server") if __name__ == "__main__": import uvicorn port = int(os.environ.get("PORT", 8080)) uvicorn.run(app, host="0.0.0.0", port=port)