#!/usr/bin/env python3

import hmac
import html
import json
import os
import re
import signal
import sqlite3
import sys
import threading
import time
import traceback
import uuid
from datetime import datetime, timezone
from http import HTTPStatus
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from urllib.parse import parse_qs, urlparse


VERSION = "0.1.0-native-agent-runtime"
MAX_BODY_BYTES = 1024 * 1024

ROOT = Path(os.environ.get("SHIRE_ROOT", "/home/shire3d/ARMOR")).resolve()
AGENT_ID = os.environ.get("SHIRE_AGENT_ID", "").strip()
HOST = os.environ.get("SHIRE_AGENT_HOST", "127.0.0.1").strip()
PORT = int(os.environ.get("SHIRE_AGENT_PORT", "8782"))
TOKEN = os.environ.get("SHIRE_AGENT_TOKEN", "")
MANIFEST_PATH = (
    ROOT / "agents" / "definitions" / AGENT_ID / "agent.manifest.json"
).resolve()
DATA_ROOT = (ROOT / "data" / "agents" / AGENT_ID).resolve()
RUNTIME_ROOT = DATA_ROOT / "runtime"
DB_PATH = RUNTIME_ROOT / f"{AGENT_ID}.sqlite3"

DB_LOCK = threading.RLock()
STARTED_MONOTONIC = time.monotonic()
STARTED_AT = datetime.now(timezone.utc).isoformat()


def utc_now():
    return datetime.now(timezone.utc).isoformat()


def load_manifest():
    with MANIFEST_PATH.open("r", encoding="utf-8") as handle:
        payload = json.load(handle)

    if payload.get("id") != AGENT_ID:
        raise RuntimeError(
            f"Manifest id {payload.get('id')!r} does not match {AGENT_ID!r}"
        )

    return payload


MANIFEST = load_manifest()
ALLOWED_CAPABILITIES = set(MANIFEST.get("capabilities", []))
BLOCKED_ACTIONS = set(MANIFEST.get("blockedActions", []))


def connect():
    connection = sqlite3.connect(DB_PATH, timeout=10)
    connection.row_factory = sqlite3.Row
    connection.execute("PRAGMA journal_mode=WAL")
    connection.execute("PRAGMA foreign_keys=ON")
    return connection


def initialise_database():
    RUNTIME_ROOT.mkdir(parents=True, exist_ok=True)

    with DB_LOCK, connect() as connection:
        connection.executescript(
            """
            CREATE TABLE IF NOT EXISTS jobs (
                id TEXT PRIMARY KEY,
                capability TEXT NOT NULL,
                status TEXT NOT NULL,
                request_json TEXT NOT NULL,
                result_json TEXT,
                approval_required INTEGER NOT NULL DEFAULT 0,
                approved_at TEXT,
                created_at TEXT NOT NULL,
                updated_at TEXT NOT NULL
            );

            CREATE TABLE IF NOT EXISTS events (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                level TEXT NOT NULL,
                event TEXT NOT NULL,
                detail_json TEXT,
                created_at TEXT NOT NULL
            );

            CREATE INDEX IF NOT EXISTS idx_jobs_status
            ON jobs(status);

            CREATE INDEX IF NOT EXISTS idx_jobs_created_at
            ON jobs(created_at);

            CREATE INDEX IF NOT EXISTS idx_events_created_at
            ON events(created_at);
            """
        )


def log_event(level, event, detail=None):
    safe_detail = detail if isinstance(detail, dict) else {"detail": detail}

    with DB_LOCK, connect() as connection:
        connection.execute(
            """
            INSERT INTO events(level, event, detail_json, created_at)
            VALUES (?, ?, ?, ?)
            """,
            (
                str(level).upper(),
                str(event),
                json.dumps(safe_detail, sort_keys=True),
                utc_now(),
            ),
        )


def public_manifest():
    return {
        "schemaVersion": MANIFEST.get("schemaVersion"),
        "id": MANIFEST.get("id"),
        "name": MANIFEST.get("name"),
        "category": MANIFEST.get("category"),
        "description": MANIFEST.get("description"),
        "capabilities": sorted(ALLOWED_CAPABILITIES),
        "blockedActions": sorted(BLOCKED_ACTIONS),
        "externalActionApprovalRequired": bool(
            MANIFEST.get("externalActionApprovalRequired", True)
        ),
        "modules": MANIFEST.get("modules", []),
        "brain": MANIFEST.get("brain", {}),
    }


def validate_number(name, value, minimum=0.01, maximum=2000.0):
    if isinstance(value, bool) or not isinstance(value, (int, float)):
        return None, f"{name} must be numeric."

    numeric = float(value)

    if numeric < minimum or numeric > maximum:
        return (
            None,
            f"{name} must be between {minimum:g} and {maximum:g} mm.",
        )

    return numeric, None


def validate_measurements(payload):
    measurements = payload.get("measurements")

    if not isinstance(measurements, dict):
        return {
            "valid": False,
            "errors": ["payload.measurements must be an object."],
            "warnings": [],
            "normalisedMeasurementsMm": {},
        }

    normalised = {}
    errors = []
    warnings = []

    for raw_name, raw_value in measurements.items():
        name = str(raw_name).strip()

        if not name:
            errors.append("Measurement names cannot be empty.")
            continue

        numeric, error = validate_number(name, raw_value)

        if error:
            errors.append(error)
            continue

        normalised[name] = round(numeric, 3)

    if len(normalised) < 3:
        errors.append(
            "At least three valid measurements are required for a useful "
            "LimbForge measurement set."
        )

    if not any(
        token in key.lower()
        for key in normalised
        for token in ("length", "height")
    ):
        warnings.append(
            "No length or height measurement was identified."
        )

    if not any(
        token in key.lower()
        for key in normalised
        for token in ("width", "circumference", "diameter")
    ):
        warnings.append(
            "No width, circumference or diameter measurement was identified."
        )

    return {
        "valid": not errors,
        "errors": errors,
        "warnings": warnings,
        "normalisedMeasurementsMm": normalised,
        "measurementCount": len(normalised),
    }


def process_capability(capability, payload):
    action = str(payload.get("action", "")).strip()

    if capability in BLOCKED_ACTIONS or action in BLOCKED_ACTIONS:
        return {
            "httpStatus": HTTPStatus.FORBIDDEN,
            "jobStatus": "blocked",
            "approvalRequired": False,
            "result": {
                "ok": False,
                "blocked": True,
                "reason": "Requested action is prohibited by the LimbForge contract.",
                "action": action or capability,
            },
        }

    if capability == "measurement.validate":
        validation = validate_measurements(payload)

        return {
            "httpStatus": (
                HTTPStatus.OK
                if validation["valid"]
                else HTTPStatus.UNPROCESSABLE_ENTITY
            ),
            "jobStatus": (
                "completed"
                if validation["valid"]
                else "validation_failed"
            ),
            "approvalRequired": False,
            "result": {
                "ok": validation["valid"],
                "capability": capability,
                "validation": validation,
                "safetyBoundary": (
                    "Measurements support cosmetic cover planning only. "
                    "They are not approved for socket fitting, load-bearing "
                    "design, implant contact or medical certification."
                ),
            },
        }

    if capability == "component.envelope":
        dimensions = payload.get("dimensionsMm", {})
        errors = []
        normalised = {}

        for key in ("width", "depth", "height"):
            numeric, error = validate_number(
                key,
                dimensions.get(key) if isinstance(dimensions, dict) else None,
            )
            if error:
                errors.append(error)
            else:
                normalised[key] = round(numeric, 3)

        if errors:
            return {
                "httpStatus": HTTPStatus.UNPROCESSABLE_ENTITY,
                "jobStatus": "validation_failed",
                "approvalRequired": False,
                "result": {
                    "ok": False,
                    "errors": errors,
                },
            }

        volume = (
            normalised["width"]
            * normalised["depth"]
            * normalised["height"]
        )

        return {
            "httpStatus": HTTPStatus.OK,
            "jobStatus": "completed",
            "approvalRequired": False,
            "result": {
                "ok": True,
                "capability": capability,
                "boundingEnvelopeMm": normalised,
                "boundingVolumeMm3": round(volume, 3),
                "clearanceApplied": False,
                "note": (
                    "This is a verified bounding-envelope calculation, not "
                    "finished cover geometry."
                ),
            },
        }

    if capability == "cover.plan":
        validation = validate_measurements(payload)

        if not validation["valid"]:
            return {
                "httpStatus": HTTPStatus.UNPROCESSABLE_ENTITY,
                "jobStatus": "validation_failed",
                "approvalRequired": False,
                "result": {
                    "ok": False,
                    "capability": capability,
                    "validation": validation,
                },
            }

        return {
            "httpStatus": HTTPStatus.CREATED,
            "jobStatus": "awaiting_approval",
            "approvalRequired": True,
            "result": {
                "ok": True,
                "capability": capability,
                "type": "safe_cosmetic_cover_plan",
                "measurements": validation["normalisedMeasurementsMm"],
                "warnings": validation["warnings"],
                "stages": [
                    "Confirm measurement provenance and units",
                    "Create non-load-bearing hardware exclusion envelope",
                    "Apply user-approved cosmetic clearance",
                    "Generate editable parametric proposal",
                    "Validate intersections, wall thickness and printability",
                    "Request approval before manufacturing preparation",
                ],
                "hardBlocks": sorted(BLOCKED_ACTIONS),
                "approval": {
                    "required": True,
                    "reason": (
                        "Generated cover plans remain proposals until Ray "
                        "approves the validated design stage."
                    ),
                },
            },
        }

    if capability == "manufacturing.prepare":
        return {
            "httpStatus": HTTPStatus.CREATED,
            "jobStatus": "awaiting_approval",
            "approvalRequired": True,
            "result": {
                "ok": True,
                "capability": capability,
                "type": "manufacturing_preparation_proposal",
                "geometryExported": False,
                "printStarted": False,
                "approval": {
                    "required": True,
                    "reason": (
                        "Manufacturing preparation cannot export or start "
                        "production without validated geometry and approval."
                    ),
                },
                "requiredEvidence": [
                    "Validated cover geometry",
                    "Clearance verification",
                    "Wall-thickness verification",
                    "Printer and material selection",
                    "Slicer-derived print-time and filament estimates",
                ],
            },
        }

    return {
        "httpStatus": HTTPStatus.ACCEPTED,
        "jobStatus": "awaiting_approval",
        "approvalRequired": True,
        "result": {
            "ok": True,
            "capability": capability,
            "message": (
                "The capability request was recorded as an approval-gated "
                "proposal. No unsupported action was claimed."
            ),
        },
    }


def create_job(capability, payload):
    job_id = f"{AGENT_ID}-{uuid.uuid4()}"
    created_at = utc_now()
    processed = process_capability(capability, payload)

    with DB_LOCK, connect() as connection:
        connection.execute(
            """
            INSERT INTO jobs(
                id,
                capability,
                status,
                request_json,
                result_json,
                approval_required,
                created_at,
                updated_at
            )
            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
            """,
            (
                job_id,
                capability,
                processed["jobStatus"],
                json.dumps(payload, sort_keys=True),
                json.dumps(processed["result"], sort_keys=True),
                1 if processed["approvalRequired"] else 0,
                created_at,
                created_at,
            ),
        )

    log_event(
        "INFO",
        "job.created",
        {
            "jobId": job_id,
            "capability": capability,
            "status": processed["jobStatus"],
        },
    )

    return job_id, processed


def row_to_job(row, include_request=True):
    result = {
        "id": row["id"],
        "capability": row["capability"],
        "status": row["status"],
        "approvalRequired": bool(row["approval_required"]),
        "approvedAt": row["approved_at"],
        "createdAt": row["created_at"],
        "updatedAt": row["updated_at"],
        "result": json.loads(row["result_json"] or "null"),
    }

    if include_request:
        result["request"] = json.loads(row["request_json"])

    return result


def fetch_job(job_id):
    with DB_LOCK, connect() as connection:
        row = connection.execute(
            "SELECT * FROM jobs WHERE id = ?",
            (job_id,),
        ).fetchone()

    return row_to_job(row) if row else None


def list_jobs(statuses=None, limit=100):
    query = "SELECT * FROM jobs"
    parameters = []

    if statuses:
        placeholders = ",".join("?" for _ in statuses)
        query += f" WHERE status IN ({placeholders})"
        parameters.extend(statuses)

    query += " ORDER BY created_at DESC LIMIT ?"
    parameters.append(max(1, min(int(limit), 500)))

    with DB_LOCK, connect() as connection:
        rows = connection.execute(query, parameters).fetchall()

    return [row_to_job(row, include_request=False) for row in rows]


def approve_job(job_id):
    now = utc_now()

    with DB_LOCK, connect() as connection:
        row = connection.execute(
            "SELECT * FROM jobs WHERE id = ?",
            (job_id,),
        ).fetchone()

        if not row:
            return None, "not_found"

        if not row["approval_required"]:
            return row_to_job(row), "approval_not_required"

        if row["status"] != "awaiting_approval":
            return row_to_job(row), "invalid_status"

        connection.execute(
            """
            UPDATE jobs
            SET status = 'approved',
                approved_at = ?,
                updated_at = ?
            WHERE id = ?
            """,
            (now, now, job_id),
        )

    log_event("INFO", "job.approved", {"jobId": job_id})
    return fetch_job(job_id), None


def cancel_job(job_id):
    now = utc_now()

    with DB_LOCK, connect() as connection:
        row = connection.execute(
            "SELECT * FROM jobs WHERE id = ?",
            (job_id,),
        ).fetchone()

        if not row:
            return None

        connection.execute(
            """
            UPDATE jobs
            SET status = 'cancelled',
                updated_at = ?
            WHERE id = ?
            """,
            (now, job_id),
        )

    log_event("INFO", "job.cancelled", {"jobId": job_id})
    return fetch_job(job_id)


def stats():
    with DB_LOCK, connect() as connection:
        total = connection.execute(
            "SELECT COUNT(*) FROM jobs"
        ).fetchone()[0]

        rows = connection.execute(
            """
            SELECT status, COUNT(*) AS count
            FROM jobs
            GROUP BY status
            ORDER BY status
            """
        ).fetchall()

    return {
        "totalJobs": total,
        "byStatus": {row["status"]: row["count"] for row in rows},
        "uptimeSeconds": round(time.monotonic() - STARTED_MONOTONIC, 3),
    }


def recent_events(limit=100):
    limit = max(1, min(int(limit), 500))

    with DB_LOCK, connect() as connection:
        rows = connection.execute(
            """
            SELECT id, level, event, detail_json, created_at
            FROM events
            ORDER BY id DESC
            LIMIT ?
            """,
            (limit,),
        ).fetchall()

    return [
        {
            "id": row["id"],
            "level": row["level"],
            "event": row["event"],
            "detail": json.loads(row["detail_json"] or "{}"),
            "createdAt": row["created_at"],
        }
        for row in rows
    ]


def dashboard_html():
    name = html.escape(str(MANIFEST.get("name", AGENT_ID)))
    description = html.escape(str(MANIFEST.get("description", "")))
    capabilities = "".join(
        f"<li><code>{html.escape(item)}</code></li>"
        for item in sorted(ALLOWED_CAPABILITIES)
    )

    return f"""<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>{name} — SHiRE Agent</title>
<style>
:root {{
  color-scheme: dark;
  font-family: Inter, ui-sans-serif, system-ui, sans-serif;
  --bg:#06080c;
  --panel:#0d1219;
  --line:#263243;
  --green:#35ef8b;
  --purple:#a76bff;
  --text:#eef5ff;
  --muted:#95a3b7;
}}
* {{ box-sizing:border-box }}
body {{
  margin:0;
  background:
    radial-gradient(circle at 75% 0,rgba(167,107,255,.16),transparent 34%),
    radial-gradient(circle at 10% 20%,rgba(53,239,139,.08),transparent 30%),
    var(--bg);
  color:var(--text);
}}
header {{
  padding:28px clamp(20px,5vw,64px);
  border-bottom:1px solid var(--line);
  background:rgba(6,8,12,.78);
  backdrop-filter:blur(18px);
}}
.badge {{
  display:inline-block;
  padding:6px 10px;
  border:1px solid rgba(53,239,139,.45);
  border-radius:999px;
  color:var(--green);
  font-size:12px;
  font-weight:800;
  letter-spacing:.12em;
}}
h1 {{ margin:14px 0 6px;font-size:clamp(30px,6vw,54px) }}
p {{ color:var(--muted);max-width:850px;line-height:1.6 }}
main {{
  width:min(1180px,calc(100% - 32px));
  margin:28px auto;
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(260px,1fr));
  gap:18px;
}}
section {{
  background:linear-gradient(145deg,rgba(18,25,35,.96),rgba(9,13,20,.96));
  border:1px solid var(--line);
  border-radius:20px;
  padding:22px;
  box-shadow:0 18px 55px rgba(0,0,0,.23);
}}
h2 {{ margin-top:0;font-size:16px;color:#dce8f7 }}
.value {{ font-size:28px;font-weight:850;color:var(--green) }}
code {{
  color:#d6b8ff;
  overflow-wrap:anywhere;
}}
li {{ margin:9px 0;color:var(--muted) }}
a {{ color:var(--green) }}
</style>
</head>
<body>
<header>
  <span class="badge">LIVE NATIVE AGENT</span>
  <h1>{name}</h1>
  <p>{description}</p>
</header>
<main>
  <section>
    <h2>Service status</h2>
    <div class="value">ONLINE</div>
    <p>Native ARMOR OS specialist runtime on {html.escape(HOST)}:{PORT}</p>
  </section>
  <section>
    <h2>Runtime version</h2>
    <div class="value">{VERSION}</div>
    <p>Agent-specific state is isolated under the ARMOR data directory.</p>
  </section>
  <section>
    <h2>Capabilities</h2>
    <ul>{capabilities}</ul>
  </section>
  <section>
    <h2>Live API</h2>
    <ul>
      <li><a href="/health">Health</a></li>
      <li><a href="/api/v1/status">Status</a></li>
      <li><a href="/api/v1/queue">Queue</a></li>
      <li><a href="/api/v1/stats">Statistics</a></li>
      <li><a href="/api/v1/logs">Logs</a></li>
      <li><a href="/api/v1/settings">Settings</a></li>
      <li><a href="/api/v1/permissions">Permissions</a></li>
    </ul>
  </section>
</main>
</body>
</html>"""


class Handler(BaseHTTPRequestHandler):
    server_version = "SHiREAgentRuntime"
    sys_version = ""

    def log_message(self, fmt, *args):
        message = fmt % args
        log_event(
            "INFO",
            "http.request",
            {
                "client": self.client_address[0],
                "message": message,
            },
        )

    def send_json(self, status, payload):
        encoded = json.dumps(
            payload,
            indent=2,
            sort_keys=True,
        ).encode("utf-8")

        self.send_response(int(status))
        self.send_header("Content-Type", "application/json; charset=utf-8")
        self.send_header("Content-Length", str(len(encoded)))
        self.send_header("Cache-Control", "no-store")
        self.send_header("X-Content-Type-Options", "nosniff")
        self.end_headers()
        self.wfile.write(encoded)

    def send_html(self, status, payload):
        encoded = payload.encode("utf-8")
        self.send_response(int(status))
        self.send_header("Content-Type", "text/html; charset=utf-8")
        self.send_header("Content-Length", str(len(encoded)))
        self.send_header("Cache-Control", "no-store")
        self.send_header("X-Content-Type-Options", "nosniff")
        self.end_headers()
        self.wfile.write(encoded)

    def read_json(self):
        raw_length = self.headers.get("Content-Length", "0")

        try:
            length = int(raw_length)
        except ValueError as exc:
            raise ValueError("Invalid Content-Length.") from exc

        if length < 1:
            return {}

        if length > MAX_BODY_BYTES:
            raise ValueError("Request body exceeds the 1 MiB limit.")

        raw = self.rfile.read(length)

        try:
            payload = json.loads(raw.decode("utf-8"))
        except Exception as exc:
            raise ValueError("Request body must contain valid JSON.") from exc

        if not isinstance(payload, dict):
            raise ValueError("Top-level JSON value must be an object.")

        return payload

    def authenticated(self):
        if not TOKEN:
            return False

        supplied = self.headers.get("Authorization", "")
        prefix = "Bearer "

        if not supplied.startswith(prefix):
            return False

        return hmac.compare_digest(supplied[len(prefix):], TOKEN)

    def require_auth(self):
        if self.authenticated():
            return True

        self.send_json(
            HTTPStatus.UNAUTHORIZED,
            {
                "ok": False,
                "error": "authentication_required",
                "message": "A valid Bearer token is required.",
            },
        )
        return False

    def do_GET(self):
        parsed = urlparse(self.path)
        path = parsed.path
        query = parse_qs(parsed.query)

        if path == "/":
            self.send_html(HTTPStatus.OK, dashboard_html())
            return

        if path in {"/health", "/api/health", "/api/v1/health"}:
            self.send_json(
                HTTPStatus.OK,
                {
                    "ok": True,
                    "service": f"shire-agent-{AGENT_ID}",
                    "agentId": AGENT_ID,
                    "name": MANIFEST.get("name"),
                    "version": VERSION,
                    "boundTo": f"{HOST}:{PORT}",
                    "startedAt": STARTED_AT,
                    "uptimeSeconds": round(
                        time.monotonic() - STARTED_MONOTONIC,
                        3,
                    ),
                    "database": str(DB_PATH),
                    "databaseReady": DB_PATH.exists(),
                    "authentication": {
                        "readEndpoints": "local_only",
                        "writeEndpoints": "bearer_token_required",
                    },
                    "publicInboundPorts": False,
                },
            )
            return

        if path == "/api/v1/status":
            self.send_json(
                HTTPStatus.OK,
                {
                    "ok": True,
                    "agent": public_manifest(),
                    "runtime": {
                        "version": VERSION,
                        "host": HOST,
                        "port": PORT,
                        "startedAt": STARTED_AT,
                    },
                    "statistics": stats(),
                },
            )
            return

        if path == "/api/v1/version":
            self.send_json(
                HTTPStatus.OK,
                {
                    "agentId": AGENT_ID,
                    "runtimeVersion": VERSION,
                    "manifestSchemaVersion": MANIFEST.get("schemaVersion"),
                },
            )
            return

        if path == "/api/v1/capabilities":
            self.send_json(
                HTTPStatus.OK,
                {
                    "agentId": AGENT_ID,
                    "capabilities": sorted(ALLOWED_CAPABILITIES),
                    "blockedActions": sorted(BLOCKED_ACTIONS),
                },
            )
            return

        if path == "/api/v1/permissions":
            self.send_json(
                HTTPStatus.OK,
                {
                    "agentId": AGENT_ID,
                    "readAccess": "localhost",
                    "writeAccess": "bearer_token",
                    "externalActionApprovalRequired": bool(
                        MANIFEST.get(
                            "externalActionApprovalRequired",
                            True,
                        )
                    ),
                    "blockedActions": sorted(BLOCKED_ACTIONS),
                },
            )
            return

        if path == "/api/v1/queue":
            queue = list_jobs(
                statuses=[
                    "queued",
                    "running",
                    "awaiting_approval",
                    "approved",
                ],
                limit=query.get("limit", ["100"])[0],
            )
            self.send_json(
                HTTPStatus.OK,
                {
                    "agentId": AGENT_ID,
                    "count": len(queue),
                    "jobs": queue,
                },
            )
            return

        if path == "/api/v1/jobs":
            jobs = list_jobs(
                limit=query.get("limit", ["100"])[0],
            )
            self.send_json(
                HTTPStatus.OK,
                {
                    "agentId": AGENT_ID,
                    "count": len(jobs),
                    "jobs": jobs,
                },
            )
            return

        job_match = re.fullmatch(r"/api/v1/jobs/([^/]+)", path)

        if job_match:
            job = fetch_job(job_match.group(1))

            if not job:
                self.send_json(
                    HTTPStatus.NOT_FOUND,
                    {
                        "ok": False,
                        "error": "job_not_found",
                    },
                )
                return

            self.send_json(HTTPStatus.OK, job)
            return

        if path == "/api/v1/logs":
            events = recent_events(
                query.get("limit", ["100"])[0],
            )
            self.send_json(
                HTTPStatus.OK,
                {
                    "agentId": AGENT_ID,
                    "count": len(events),
                    "events": events,
                },
            )
            return

        if path == "/api/v1/stats":
            self.send_json(
                HTTPStatus.OK,
                {
                    "agentId": AGENT_ID,
                    **stats(),
                },
            )
            return

        if path == "/api/v1/settings":
            self.send_json(
                HTTPStatus.OK,
                {
                    "agentId": AGENT_ID,
                    "host": HOST,
                    "port": PORT,
                    "database": str(DB_PATH),
                    "manifest": str(MANIFEST_PATH),
                    "dataRoot": str(DATA_ROOT),
                    "authenticationConfigured": bool(TOKEN),
                    "externalActionApprovalRequired": bool(
                        MANIFEST.get(
                            "externalActionApprovalRequired",
                            True,
                        )
                    ),
                },
            )
            return

        self.send_json(
            HTTPStatus.NOT_FOUND,
            {
                "ok": False,
                "error": "not_found",
                "path": path,
            },
        )

    def do_POST(self):
        parsed = urlparse(self.path)
        path = parsed.path

        if not self.require_auth():
            return

        try:
            payload = self.read_json()
        except ValueError as exc:
            self.send_json(
                HTTPStatus.BAD_REQUEST,
                {
                    "ok": False,
                    "error": "invalid_request",
                    "message": str(exc),
                },
            )
            return

        if path == "/api/v1/jobs":
            capability = str(payload.get("capability", "")).strip()
            request_payload = payload.get("payload", {})

            if capability not in ALLOWED_CAPABILITIES:
                self.send_json(
                    HTTPStatus.BAD_REQUEST,
                    {
                        "ok": False,
                        "error": "unsupported_capability",
                        "capability": capability,
                        "allowedCapabilities": sorted(
                            ALLOWED_CAPABILITIES
                        ),
                    },
                )
                return

            if not isinstance(request_payload, dict):
                self.send_json(
                    HTTPStatus.BAD_REQUEST,
                    {
                        "ok": False,
                        "error": "invalid_payload",
                        "message": "payload must be an object.",
                    },
                )
                return

            job_id, processed = create_job(
                capability,
                request_payload,
            )
            job = fetch_job(job_id)

            self.send_json(
                processed["httpStatus"],
                {
                    "ok": processed["result"].get("ok", False),
                    "job": job,
                },
            )
            return

        approve_match = re.fullmatch(
            r"/api/v1/jobs/([^/]+)/approve",
            path,
        )

        if approve_match:
            job, error = approve_job(approve_match.group(1))

            if error == "not_found":
                self.send_json(
                    HTTPStatus.NOT_FOUND,
                    {
                        "ok": False,
                        "error": "job_not_found",
                    },
                )
                return

            if error:
                self.send_json(
                    HTTPStatus.CONFLICT,
                    {
                        "ok": False,
                        "error": error,
                        "job": job,
                    },
                )
                return

            self.send_json(
                HTTPStatus.OK,
                {
                    "ok": True,
                    "job": job,
                },
            )
            return

        cancel_match = re.fullmatch(
            r"/api/v1/jobs/([^/]+)/cancel",
            path,
        )

        if cancel_match:
            job = cancel_job(cancel_match.group(1))

            if not job:
                self.send_json(
                    HTTPStatus.NOT_FOUND,
                    {
                        "ok": False,
                        "error": "job_not_found",
                    },
                )
                return

            self.send_json(
                HTTPStatus.OK,
                {
                    "ok": True,
                    "job": job,
                },
            )
            return

        if path == "/api/v1/restart/request":
            request_id = f"restart-{uuid.uuid4()}"
            log_event(
                "WARNING",
                "restart.requested",
                {
                    "requestId": request_id,
                    "executed": False,
                    "reason": payload.get("reason", ""),
                },
            )
            self.send_json(
                HTTPStatus.ACCEPTED,
                {
                    "ok": True,
                    "requestId": request_id,
                    "executed": False,
                    "approvalRequired": True,
                    "message": (
                        "The restart request was recorded. The Agent cannot "
                        "grant itself systemd authority."
                    ),
                },
            )
            return

        self.send_json(
            HTTPStatus.NOT_FOUND,
            {
                "ok": False,
                "error": "not_found",
                "path": path,
            },
        )


def main():
    if not AGENT_ID:
        raise RuntimeError("SHIRE_AGENT_ID is required.")

    if not TOKEN:
        raise RuntimeError("SHIRE_AGENT_TOKEN is required.")

    initialise_database()
    log_event(
        "INFO",
        "runtime.started",
        {
            "agentId": AGENT_ID,
            "version": VERSION,
            "host": HOST,
            "port": PORT,
        },
    )

    server = ThreadingHTTPServer((HOST, PORT), Handler)

    def stop_server(signum, frame):
        log_event(
            "INFO",
            "runtime.stopping",
            {"signal": signum},
        )
        threading.Thread(
            target=server.shutdown,
            daemon=True,
        ).start()

    signal.signal(signal.SIGTERM, stop_server)
    signal.signal(signal.SIGINT, stop_server)

    print(
        f"{AGENT_ID} runtime {VERSION} listening on {HOST}:{PORT}",
        flush=True,
    )

    try:
        server.serve_forever(poll_interval=0.5)
    finally:
        server.server_close()
        log_event("INFO", "runtime.stopped", {})


if __name__ == "__main__":
    try:
        main()
    except Exception:
        traceback.print_exc()
        sys.exit(1)
