"""Dependency-light HTTP server for the cabin orchestration demo.""" from __future__ import annotations import argparse import hmac import ipaddress import json import mimetypes import os import re import socket from http.cookies import CookieError, SimpleCookie from http import HTTPStatus from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from pathlib import Path from urllib.parse import ParseResult, parse_qs, quote, unquote, urlparse from cognitive_agent.config_loader import load_local_env REPOSITORY_ROOT = Path(__file__).resolve().parents[2] # Repository-local launch configuration is deliberate and must not be shadowed # by stale variables inherited from an IDE or an earlier model experiment. load_local_env(REPOSITORY_ROOT / ".env", override=True) load_local_env(REPOSITORY_ROOT / ".env.auth", override=True) from cognitive_agent.auth import AuthConfig, AuthRuntime, verify_password # noqa: E402 from cognitive_agent.application.seat_service import SeatDemoService # noqa: E402 from cognitive_agent.application.gesture_bridge import GestureCapabilityBridge # noqa: E402 from cognitive_agent.application.calibration.service import ( # noqa: E402 ApiError as CalibrationApiError, CalibrationService, ) from cognitive_agent.application.self_extension import ( # noqa: E402 ExtensionIntegrationError, GatewayError, SelfExtensionService, ) from cognitive_agent.application.self_repair import SelfRepairService # noqa: E402 from cognitive_agent.infrastructure.can.hardware import ( # noqa: E402 HardwareBusyError, HardwareSafetyError, ) from cognitive_agent.infrastructure.can.access import ( # noqa: E402 HardwareAccessRequiredError, ) from cognitive_agent.infrastructure.llm.openai_responses import OpenAIIntentError # noqa: E402 STATIC_ROOT = REPOSITORY_ROOT / "apps" / "web-console" mimetypes.add_type("application/manifest+json", ".webmanifest") mimetypes.add_type("model/gltf-binary", ".glb") REQUEST_ID_PATTERN = re.compile(r"^req-[a-z0-9-]+$") PUBLIC_AUTH_PATHS = { "/login", "/login.html", "/login.css", "/login.js", "/network.js", "/api/auth/status", "/api/auth/login", } def _lan_ipv4_address() -> str | None: """Return the IPv4 address selected by the host's default route.""" probe = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: probe.connect(("192.0.2.1", 80)) address = str(probe.getsockname()[0]) return None if address.startswith("127.") else address except OSError: return None finally: probe.close() class SeatDemoHandler(BaseHTTPRequestHandler): service = SeatDemoService() gesture = GestureCapabilityBridge(REPOSITORY_ROOT) extension = SelfExtensionService() calibration = CalibrationService( REPOSITORY_ROOT / "artifacts" / "tmp" / "self-calibration", repository_root=REPOSITORY_ROOT, ) repair = SelfRepairService() auth = AuthRuntime(AuthConfig.from_env()) server_version = "CognitiveAgentCabinDemo/2.0" def do_GET(self) -> None: # noqa: N802 - stdlib handler API parsed_url = urlparse(self.path) path = unquote(parsed_url.path) if path == "/favicon.ico": self.send_response(HTTPStatus.NO_CONTENT) self._send_security_headers() self.end_headers() return if path == "/api/auth/status": username = self._session_username() self._json( { "enabled": self.auth.config.enabled, "authenticated": not self.auth.config.enabled or username is not None, "username": username, "session_ttl_seconds": self.auth.config.session_ttl_seconds, "requests_per_minute": self.auth.config.requests_per_minute, } ) return if path in {"/login", "/login.html"}: if self.auth.config.enabled and self._session_username() is not None: self._redirect("/") return self._serve_static_file("login.html") return if not self._authorize(path): return if path in {"/hardware-control", "/hardware-control.html"}: if not self._require_local_decision_point(): return self._serve_static_file("hardware-control.html") return if path in {"/hardware-control.js", "/hardware-control.css"}: if not self._require_local_decision_point(): return self._serve_static_file(path.lstrip("/")) return if path == "/api/local/hardware-access": if not self._require_local_decision_point(): return self._json(self.service.hardware_access.admin_snapshot()) return if path == "/api/hardware/access/status": query = parse_qs(parsed_url.query) try: self._json( self.service.hardware_access.status( str(query.get("client_id", [""])[0]) ) ) except ValueError as exc: self._json( {"error": "invalid_request", "message": str(exc)}, HTTPStatus.BAD_REQUEST, ) return if path == "/api/health": self._json({"status": "ok", "service": "cabin-cognitive-orchestrator"}) return if path == "/api/runtime": self._json(self.service.runtime_info()) return if path in {"/api/hardware/seat-state", "/api/hardware/vehicle-state"}: query = parse_qs(parsed_url.query) conversation_id = str(query.get("conversation_id", [""])[0]) vehicle_id = str(query.get("vehicle_id", [""])[0]) or None hardware_client_id = str(query.get("hardware_client_id", [""])[0]) or None try: self._json( ( self.service.synchronize_vehicle_state if path == "/api/hardware/vehicle-state" else self.service.synchronize_hardware_state )( conversation_id, vehicle_id, hardware_client_id=hardware_client_id, hardware_access_bypass=self._is_unproxied_loopback_request(), ) ) except HardwareAccessRequiredError as exc: self._json( { "error": "hardware_access_required", "message": str(exc), "access_state": exc.state, }, HTTPStatus.FORBIDDEN, ) except HardwareBusyError as exc: self._json( { "error": "hardware_busy", "message": str(exc), "retry_after_seconds": exc.retry_after_seconds, }, HTTPStatus.CONFLICT, {"Retry-After": str(exc.retry_after_seconds)}, ) except ValueError as exc: self._json( {"error": "invalid_request", "message": str(exc)}, HTTPStatus.BAD_REQUEST, ) except Exception as exc: # noqa: BLE001 - surface passive CAN availability self.log_error("physical CAN state synchronization failed: %s", exc) self._json( { "error": "hardware_state_unavailable", "message": str(exc), }, HTTPStatus.SERVICE_UNAVAILABLE, ) return if path == "/api/gesture/runtime": self._json(self.gesture.runtime_info()) return if path == "/api/gesture/model": self._serve_gesture_model() return if path == "/api/extension/health": self._json(self.extension.health()) return if path == "/api/extension/gscu/info": self._handle_extension_gateway("info", {}) return if path.startswith("/api/calibration/"): if not self._require_calibration_admin(parsed_url): return if path == "/api/calibration/state": self._json(self.calibration.snapshot()) return if path == "/api/calibration/events": self._serve_calibration_events() return if path == "/api/calibration/video/stream": self._serve_calibration_video() return self._json({"error": "not_found"}, HTTPStatus.NOT_FOUND) return if path.startswith("/api/self-repair/"): if not self._require_self_repair_admin(parsed_url): return if path == "/api/self-repair/state": self._json(self.repair.snapshot()) return if path == "/api/self-repair/health": self._json(self.repair.health()) return self._json({"error": "not_found"}, HTTPStatus.NOT_FOUND) return if path.startswith("/api/requests/"): self._serve_request(path.removeprefix("/api/requests/")) return self._serve_static(path) def do_POST(self) -> None: # noqa: N802 - stdlib handler API path = unquote(urlparse(self.path).path) if path == "/api/auth/login": self._login() return if path == "/api/auth/logout": self._logout() return if not self._authorize(path): return if path in { "/api/hardware/access/request", "/api/hardware/access/release", "/api/local/hardware-access/approve", "/api/local/hardware-access/deny", "/api/local/hardware-access/revoke", }: self._handle_hardware_access_post(path) return if path.startswith("/api/extension/"): self._handle_extension_post(path) return if path.startswith("/api/calibration/"): self._handle_calibration_post(path) return if path.startswith("/api/self-repair/"): self._handle_self_repair_post(path) return if path != "/api/requests": self._json({"error": "not_found"}, HTTPStatus.NOT_FOUND) return try: username = self._session_username() or "local" retry_after = self.auth.api_requests.retry_after(username) if self.auth.config.enabled and retry_after: self._json( { "error": "rate_limited", "message": "请求过于频繁,请稍后再试。", }, HTTPStatus.TOO_MANY_REQUESTS, {"Retry-After": str(retry_after)}, ) return if self.auth.config.enabled: self.auth.api_requests.record(username) payload = self._read_json_body() result = self.service.process( str(payload.get("utterance", "")), str(payload.get("provider", "auto")), str(payload["conversation_id"]) if payload.get("conversation_id") else None, str(payload.get("execution_mode", "dry_run")), # Hardware authorization is a server deployment policy. The # browser no longer renders or transmits an approval secret. approval_token=os.getenv("COGNITIVE_AGENT_HARDWARE_APPROVAL_TOKEN"), vehicle_id=( str(payload["vehicle_id"]) if payload.get("vehicle_id") else None ), simulation_fault=str(payload.get("simulation_fault", "normal")), hardware_client_id=( str(payload["hardware_client_id"]) if payload.get("hardware_client_id") else None ), hardware_access_bypass=self._is_unproxied_loopback_request(), ) self._json(result, HTTPStatus.CREATED) except HardwareAccessRequiredError as exc: self._json( { "error": "hardware_access_required", "message": str(exc), "access_state": exc.state, }, HTTPStatus.FORBIDDEN, ) except HardwareBusyError as exc: self._json( { "error": "hardware_busy", "message": str(exc), "retry_after_seconds": exc.retry_after_seconds, }, HTTPStatus.CONFLICT, {"Retry-After": str(exc.retry_after_seconds)}, ) except HardwareSafetyError as exc: self._json( {"error": "hardware_safety_gate", "message": str(exc)}, HTTPStatus.FORBIDDEN, ) except (ValueError, json.JSONDecodeError) as exc: self._json({"error": "invalid_request", "message": str(exc)}, HTTPStatus.BAD_REQUEST) except OpenAIIntentError as exc: self.log_error("OpenAI intent request failed: %s", exc) self._json( { "error": "openai_request_failed", "message": "GPT 意图解析失败,请检查 API Key、模型权限或网络状态。", }, HTTPStatus.BAD_GATEWAY, ) except Exception as exc: # noqa: BLE001 - keep the demo API responsive self.log_error("request failed: %s", exc) self._json( { "error": "internal_error", "message": "请求处理失败,请查看服务端日志。", }, HTTPStatus.INTERNAL_SERVER_ERROR, ) def do_DELETE(self) -> None: # noqa: N802 - stdlib handler API parsed_url = urlparse(self.path) path = unquote(parsed_url.path) if not self._authorize(path): return prefix = "/api/mode-profiles/" if not path.startswith(prefix): self._json({"error": "not_found"}, HTTPStatus.NOT_FOUND) return mode_id = path.removeprefix(prefix).strip() vehicle_id = str(parse_qs(parsed_url.query).get("vehicle_id", [""])[0]) or None try: self._json( self.service.delete_user_mode_profile(mode_id, vehicle_id), HTTPStatus.OK, ) except KeyError: self._json( {"error": "not_found", "message": "未找到可删除的用户自定义模式。"}, HTTPStatus.NOT_FOUND, ) except PermissionError as exc: self._json( {"error": "preset_mode_protected", "message": str(exc)}, HTTPStatus.FORBIDDEN, ) except ValueError as exc: self._json( {"error": "invalid_request", "message": str(exc)}, HTTPStatus.BAD_REQUEST, ) def _handle_extension_post(self, path: str) -> None: action_map = { "/api/extension/gscu/learn": "learn", "/api/extension/gscu/cancel": "cancel", "/api/extension/gscu/emit": "emit", "/api/extension/gscu/read": "read", "/api/extension/gscu/erase": "erase", } try: payload = self._read_json_body(max_bytes=256 * 1024) action = action_map.get(path) if action: self._handle_extension_gateway(action, payload) return if path == "/api/extension/assistant/plan": self._json(self.extension.plan(payload)) return if path == "/api/extension/vehicle/execute": result = self.extension.execute_vehicle( payload, self.service, hardware_access_bypass=self._is_unproxied_loopback_request(), ) self._json(result) return self._json({"error": "not_found"}, HTTPStatus.NOT_FOUND) except GatewayError as exc: self._json( {"success": False, "error": "gscu_unavailable", "message": str(exc)}, HTTPStatus.SERVICE_UNAVAILABLE, ) except ExtensionIntegrationError as exc: self._json( {"success": False, "error": "extension_unavailable", "message": str(exc)}, HTTPStatus.SERVICE_UNAVAILABLE, ) except HardwareAccessRequiredError as exc: self._json( { "success": False, "error": "hardware_access_required", "message": str(exc), "access_state": exc.state, }, HTTPStatus.FORBIDDEN, ) except HardwareBusyError as exc: self._json( { "success": False, "error": "hardware_busy", "message": str(exc), "retry_after_seconds": exc.retry_after_seconds, }, HTTPStatus.CONFLICT, {"Retry-After": str(exc.retry_after_seconds)}, ) except HardwareSafetyError as exc: self._json( {"success": False, "error": "hardware_safety_gate", "message": str(exc)}, HTTPStatus.FORBIDDEN, ) except OpenAIIntentError as exc: self.log_error("extension vehicle intent request failed: %s", exc) self._json( { "success": False, "error": "openai_request_failed", "message": "车端 GPT 意图解析失败,请检查模型配置。", }, HTTPStatus.BAD_GATEWAY, ) except (ValueError, json.JSONDecodeError) as exc: self._json( {"success": False, "error": "invalid_request", "message": str(exc)}, HTTPStatus.BAD_REQUEST, ) except Exception as exc: # noqa: BLE001 - keep extension APIs responsive self.log_error("self-extension request failed: %s", exc) self._json( { "success": False, "error": "internal_error", "message": "自扩展服务处理失败,请查看服务端日志。", }, HTTPStatus.INTERNAL_SERVER_ERROR, ) def _handle_calibration_post(self, path: str) -> None: if not self._require_calibration_admin(): return try: payload = self._read_json_body(max_bytes=256 * 1024) action_map = { "/api/calibration/can/connect": lambda: self.calibration.connect_can( dict(payload.get("can", payload)) ), "/api/calibration/start": lambda: self.calibration.calibrate( None if payload.get("axis", "all") == "all" else int(payload["axis"]) ), "/api/calibration/move": lambda: self.calibration.move( int(payload["axis"]), int(payload["permille"]) ), "/api/calibration/seek": lambda: self.calibration.seek( int(payload["axis"]), bool(payload.get("far")) ), "/api/calibration/stop": self.calibration.stop, "/api/calibration/settings": lambda: self.calibration.update_settings( dict(payload) ), "/api/calibration/mqtt/connect": self.calibration.connect_mqtt, "/api/calibration/mqtt/disconnect": self.calibration.disconnect_mqtt, "/api/calibration/mqtt/test": self.calibration.mqtt_test, "/api/calibration/video/start": self.calibration.start_video, "/api/calibration/video/stop": self.calibration.stop_video, } action = action_map.get(path) if action is None: self._json({"error": "not_found"}, HTTPStatus.NOT_FOUND) return requested_mode = str( dict(payload.get("can", {})).get( "mode", self.calibration.snapshot()["transport"]["mode"] ) ) motion_paths = { "/api/calibration/can/connect", "/api/calibration/start", "/api/calibration/move", "/api/calibration/seek", "/api/calibration/stop", } if path in motion_paths and requested_mode == "hardware": if not self._require_local_decision_point(): return self._json({"ok": True, "state": action()}) except CalibrationApiError as exc: self._json( {"ok": False, "error": "calibration_error", "message": str(exc)}, HTTPStatus(exc.status), ) except (KeyError, TypeError, ValueError, json.JSONDecodeError) as exc: self._json( {"ok": False, "error": "invalid_request", "message": str(exc)}, HTTPStatus.BAD_REQUEST, ) except Exception as exc: # noqa: BLE001 - keep calibration APIs responsive self.log_error("self-calibration request failed: %s", exc) self._json( { "ok": False, "error": "internal_error", "message": "自标定服务处理失败,请查看服务端日志。", }, HTTPStatus.INTERNAL_SERVER_ERROR, ) def _handle_self_repair_post(self, path: str) -> None: if not self._require_self_repair_admin(): return try: payload = self._read_json_body(max_bytes=256 * 1024) physical_paths = { "/api/self-repair/hardware/start", "/api/self-repair/hardware/stop", "/api/self-repair/emergency-stop", "/api/self-repair/firmware/build-flash", "/api/self-repair/open-log", } if ( path in physical_paths or ( path in { "/api/self-repair/healing/start", "/api/self-repair/healing/reset", } and str(payload.get("execution_mode", "shadow")) == "bench" ) ) and not self._require_local_decision_point(): return if path == "/api/self-repair/healing/start": self._json({"ok": True, "healing": self.repair.start_healing(payload)}) return if path == "/api/self-repair/healing/run-all": self._json({"ok": True, "batch": self.repair.start_batch(payload)}) return if path == "/api/self-repair/healing/reset": self._json({"ok": True, **self.repair.reset_healing(payload)}) return if path == "/api/self-repair/hardware/start": self._json({"ok": True, "session": self.repair.start_hardware()}) return if path == "/api/self-repair/hardware/stop": self._json({"ok": True, "session": self.repair.stop_hardware()}) return if path == "/api/self-repair/hardware/self-test": self._json( {"ok": True, "self_test": self.repair.run_hardware_self_test()} ) return if path == "/api/self-repair/emergency-stop": self._json({"ok": True, "request": self.repair.emergency_stop()}) return if path == "/api/self-repair/snapshot": self._json({"ok": True, "path": str(self.repair.save_snapshot())}) return if path == "/api/self-repair/firmware/build-flash": self._json( { "ok": True, "firmware": self.repair.build_and_flash_firmware(payload), } ) return if path == "/api/self-repair/open-log": opened = self.repair.open_log_dir() self._json({"ok": opened}) return self._json({"error": "not_found"}, HTTPStatus.NOT_FOUND) except (KeyError, TypeError, ValueError, json.JSONDecodeError) as exc: self._json( {"ok": False, "error": "invalid_request", "message": str(exc)}, HTTPStatus.BAD_REQUEST, ) except Exception as exc: # noqa: BLE001 - keep self-repair API responsive self.log_error("self-repair request failed: %s", exc) self._json( { "ok": False, "error": "internal_error", "message": "自修复服务处理失败,请查看服务端日志。", }, HTTPStatus.INTERNAL_SERVER_ERROR, ) def _require_self_repair_admin(self, parsed_url: ParseResult | None = None) -> bool: role = self.headers.get("X-Cognitive-Agent-Role", "").strip().lower() if not role and parsed_url is not None: role = str(parse_qs(parsed_url.query).get("role", [""])[0]).lower() if hmac.compare_digest(role, "admin"): return True self._json( {"error": "admin_required", "message": "自修复仅对 admin 开放。"}, HTTPStatus.FORBIDDEN, ) return False def _require_calibration_admin(self, parsed_url: ParseResult | None = None) -> bool: role = self.headers.get("X-Cognitive-Agent-Role", "").strip().lower() if not role and parsed_url is not None: role = str(parse_qs(parsed_url.query).get("role", [""])[0]).lower() if hmac.compare_digest(role, "admin"): return True self._json( { "error": "admin_required", "message": "自标定仅对 admin 开放。", }, HTTPStatus.FORBIDDEN, ) return False def _serve_calibration_events(self) -> None: self.send_response(HTTPStatus.OK) self.send_header("Content-Type", "text/event-stream; charset=utf-8") self.send_header("Cache-Control", "no-cache") self.send_header("Connection", "keep-alive") self.send_header("X-Accel-Buffering", "no") self._send_security_headers() self.end_headers() version = -1 try: while True: state = self.calibration.wait_for_version(version, 12.0) version = state["version"] data = json.dumps(state, ensure_ascii=False, separators=(",", ":")) self.wfile.write(f"data: {data}\n\n".encode("utf-8")) self.wfile.flush() except (BrokenPipeError, ConnectionResetError, ConnectionAbortedError): pass def _serve_calibration_video(self) -> None: self.send_response(HTTPStatus.OK) self.send_header("Content-Type", "multipart/x-mixed-replace; boundary=n7frame") self.send_header("Cache-Control", "no-store") self.send_header("Connection", "close") self._send_security_headers() self.end_headers() sequence = -1 try: while True: sequence, frame = self.calibration.video.wait_frame(sequence) if frame is None: continue header = ( b"--n7frame\r\nContent-Type: image/jpeg\r\nContent-Length: " + str(len(frame)).encode("ascii") + b"\r\n\r\n" ) self.wfile.write(header + frame + b"\r\n") self.wfile.flush() except (BrokenPipeError, ConnectionResetError, ConnectionAbortedError): pass def _handle_extension_gateway(self, action: str, payload: dict[str, object]) -> None: try: self._json(self.extension.execute_gateway(action, dict(payload))) except GatewayError as exc: self._json( {"success": False, "error": "gscu_unavailable", "message": str(exc)}, HTTPStatus.SERVICE_UNAVAILABLE, ) def _handle_hardware_access_post(self, path: str) -> None: local_path = path.startswith("/api/local/") if local_path and not self._require_local_decision_point(): return try: payload = self._read_json_body(max_bytes=4096) client_id = str(payload.get("client_id", "")) if path == "/api/hardware/access/request": status = self.service.hardware_access.request_access( client_id, str(payload.get("label", "")), self._client_key(), ) self._json( status, HTTPStatus.OK if status["state"] == "approved" else HTTPStatus.ACCEPTED, ) return if path == "/api/hardware/access/release": self._json(self.service.hardware_access.release(client_id)) return if path == "/api/local/hardware-access/approve": self._json(self.service.hardware_access.approve(client_id)) return if path == "/api/local/hardware-access/deny": self._json(self.service.hardware_access.deny(client_id)) return if path == "/api/local/hardware-access/revoke": self._json( self.service.hardware_access.revoke(client_id or None) ) return except (ValueError, json.JSONDecodeError) as exc: self._json( {"error": "invalid_request", "message": str(exc)}, HTTPStatus.BAD_REQUEST, ) def _read_json_body(self, max_bytes: int = 32768) -> dict[str, object]: content_length = int(self.headers.get("Content-Length", "0")) if content_length <= 0 or content_length > max_bytes: raise ValueError(f"request body must be between 1 and {max_bytes} bytes") payload = json.loads(self.rfile.read(content_length).decode("utf-8")) if not isinstance(payload, dict): raise ValueError("request body must be a JSON object") return payload def _authorize(self, path: str) -> bool: if not self.auth.config.enabled or path in PUBLIC_AUTH_PATHS: return True if self._session_username() is not None: return True if path.startswith("/api/"): self._json( { "error": "authentication_required", "message": "请登录后访问。", }, HTTPStatus.UNAUTHORIZED, ) else: requested = path if path.startswith("/") else "/" self._redirect(f"/login?next={quote(requested, safe='/')}") return False def _login(self) -> None: if not self.auth.config.enabled: self._json({"enabled": False, "authenticated": True}) return client_key = self._client_key() retry_after = self.auth.login_failures.retry_after(client_key) if retry_after: self._json( { "error": "login_rate_limited", "message": "登录尝试过多,请稍后再试。", }, HTTPStatus.TOO_MANY_REQUESTS, {"Retry-After": str(retry_after)}, ) return try: content_length = int(self.headers.get("Content-Length", "0")) if content_length <= 0 or content_length > 4096: raise ValueError("invalid login body") payload = json.loads(self.rfile.read(content_length).decode("utf-8")) if not isinstance(payload, dict): raise ValueError("invalid login body") username = str(payload.get("username", ""))[:128] password = str(payload.get("password", ""))[:1024] except (ValueError, json.JSONDecodeError): self._json( {"error": "invalid_request", "message": "登录请求格式无效。"}, HTTPStatus.BAD_REQUEST, ) return password_valid = verify_password(password, self.auth.config.password_hash) username_valid = hmac.compare_digest( username.encode("utf-8"), self.auth.config.username.encode("utf-8"), ) if not (username_valid and password_valid): self.auth.login_failures.record(client_key) self._json( {"error": "invalid_credentials", "message": "用户名或密码错误。"}, HTTPStatus.UNAUTHORIZED, ) return self.auth.login_failures.clear(client_key) token = self.auth.sessions.issue(self.auth.config.username) attributes = [ f"{self.auth.config.cookie_name}={token}", "Path=/", "HttpOnly", "SameSite=Strict", f"Max-Age={self.auth.config.session_ttl_seconds}", ] if self._is_https(): attributes.append("Secure") self._json( { "authenticated": True, "username": self.auth.config.username, }, headers={"Set-Cookie": "; ".join(attributes)}, ) def _logout(self) -> None: attributes = [ f"{self.auth.config.cookie_name}=", "Path=/", "HttpOnly", "SameSite=Strict", "Max-Age=0", ] if self._is_https(): attributes.append("Secure") self._json( {"authenticated": False}, headers={"Set-Cookie": "; ".join(attributes)}, ) def _session_username(self) -> str | None: if not self.auth.config.enabled: return None cookie_header = self.headers.get("Cookie", "") if not cookie_header or len(cookie_header) > 4096: return None try: cookies = SimpleCookie() cookies.load(cookie_header) morsel = cookies.get(self.auth.config.cookie_name) return self.auth.sessions.verify(morsel.value if morsel else "") except (CookieError, ValueError): return None def _client_key(self) -> str: address = self.client_address[0] direct_address = ipaddress.ip_address(address) if self.auth.config.trust_proxy_headers and direct_address.is_loopback: forwarded = ( self.headers.get("CF-Connecting-IP") or self.headers.get("X-Forwarded-For", "").split(",", 1)[0] ).strip() try: address = str(ipaddress.ip_address(forwarded)) except ValueError: pass return address def _is_unproxied_loopback_request(self) -> bool: """Distinguish the local decision console from traffic via the tunnel.""" try: direct_address = ipaddress.ip_address(self.client_address[0]) except ValueError: return False proxy_headers = ( "Forwarded", "X-Forwarded-For", "X-Real-IP", "CF-Connecting-IP", ) return direct_address.is_loopback and not any( self.headers.get(name, "").strip() for name in proxy_headers ) def _require_local_decision_point(self) -> bool: if self._is_unproxied_loopback_request(): return True self._json( { "error": "local_access_required", "message": "真实台架审批与停止权限仅在台架本机开放。", }, HTTPStatus.FORBIDDEN, ) return False def _is_https(self) -> bool: if not self.auth.config.trust_proxy_headers: return False if self.headers.get("X-Forwarded-Proto", "").lower() == "https": return True return '"scheme":"https"' in self.headers.get("CF-Visitor", "").replace(" ", "") def _serve_request(self, request_id: str) -> None: if not REQUEST_ID_PATTERN.fullmatch(request_id): self._json({"error": "invalid_request_id"}, HTTPStatus.BAD_REQUEST) return result_path = self.service.artifact_root / request_id / "result.json" if not result_path.is_file(): self._json({"error": "not_found"}, HTTPStatus.NOT_FOUND) return self._json(json.loads(result_path.read_text(encoding="utf-8"))) def _serve_static(self, path: str) -> None: relative_path = "index.html" if path in {"", "/"} else path.lstrip("/") self._serve_static_file(relative_path) def _serve_static_file(self, relative_path: str) -> None: candidate = (STATIC_ROOT / relative_path).resolve() try: candidate.relative_to(STATIC_ROOT.resolve()) except ValueError: self._json({"error": "not_found"}, HTTPStatus.NOT_FOUND) return if not candidate.is_file(): candidate = STATIC_ROOT / "index.html" content_type, _ = mimetypes.guess_type(candidate.name) content = candidate.read_bytes() self.send_response(HTTPStatus.OK) resolved_content_type = content_type or "application/octet-stream" if resolved_content_type.startswith("text/") or resolved_content_type in { "application/javascript", "application/json", "application/manifest+json", "image/svg+xml", }: resolved_content_type = f"{resolved_content_type}; charset=utf-8" self.send_header( "Content-Type", resolved_content_type, ) self.send_header("Content-Length", str(len(content))) cache_control = "no-cache" if relative_path.startswith(("vendor/", "assets/", "icons/")): cache_control = "public, max-age=31536000, immutable" elif candidate.name in {"index.html", "login.html", "service-worker.js"}: cache_control = "no-cache" self.send_header("Cache-Control", cache_control) if candidate.name == "service-worker.js": self.send_header("Service-Worker-Allowed", "/") self._send_security_headers() self.end_headers() self.wfile.write(content) def _serve_gesture_model(self) -> None: path = self.gesture.model_path if not path.is_file(): self._json( {"error": "gesture_model_unavailable", "message": "手势模型文件不可用。"}, HTTPStatus.NOT_FOUND, ) return content = path.read_bytes() self.send_response(HTTPStatus.OK) self.send_header("Content-Type", "application/octet-stream") self.send_header("Content-Length", str(len(content))) self.send_header("Cache-Control", "private, max-age=3600") self._send_security_headers() self.end_headers() self.wfile.write(content) def _json( self, payload: object, status: HTTPStatus = HTTPStatus.OK, headers: dict[str, str] | None = None, ) -> None: content = json.dumps(payload, ensure_ascii=False).encode("utf-8") self.send_response(status) self.send_header("Content-Type", "application/json; charset=utf-8") self.send_header("Content-Length", str(len(content))) self.send_header("Cache-Control", "no-store") for name, value in (headers or {}).items(): self.send_header(name, value) self._send_security_headers() self.end_headers() self.wfile.write(content) def _redirect(self, location: str) -> None: self.send_response(HTTPStatus.SEE_OTHER) self.send_header("Location", location) self.send_header("Cache-Control", "no-store") self._send_security_headers() self.end_headers() def _send_security_headers(self) -> None: self.send_header("X-Content-Type-Options", "nosniff") self.send_header("X-Frame-Options", "DENY") self.send_header("Referrer-Policy", "no-referrer") self.send_header( "Permissions-Policy", "camera=(self), microphone=(), geolocation=(), payment=(), usb=()", ) self.send_header( "Content-Security-Policy", "default-src 'self'; " "script-src 'self' 'wasm-unsafe-eval'; " "style-src 'self'; " "img-src 'self' data: blob:; " "connect-src 'self' blob:; " "object-src 'none'; base-uri 'none'; frame-ancestors 'none'", ) if self._is_https(): self.send_header( "Strict-Transport-Security", "max-age=31536000; includeSubDomains", ) def main() -> None: parser = argparse.ArgumentParser(description="Run the cabin orchestration demo") parser.add_argument("--host", default=os.getenv("HOST", "127.0.0.1")) parser.add_argument("--port", type=int, default=int(os.getenv("PORT", "8000"))) args = parser.parse_args() server = ThreadingHTTPServer((args.host, args.port), SeatDemoHandler) SeatDemoHandler.extension.start() SeatDemoHandler.calibration.start() SeatDemoHandler.repair.start() if args.host in {"0.0.0.0", "::"}: lan_address = _lan_ipv4_address() print(f"Cabin orchestration demo (local): http://127.0.0.1:{args.port}", flush=True) if lan_address: print( f"Cabin orchestration demo (LAN): http://{lan_address}:{args.port}", flush=True, ) print( "LAN mode: devices on reachable networks can use the GPT-backed API.", flush=True, ) else: print(f"Cabin orchestration demo: http://{args.host}:{args.port}", flush=True) hardware = SeatDemoHandler.service.hardware_settings print( "Execution modes: dry_run + simulated_hardware " f"({'enabled' if SeatDemoHandler.service.simulated_hardware_enabled else 'locked'}) " "+ hardware " f"({'configured' if hardware.configured else 'locked'})", flush=True, ) try: server.serve_forever() except KeyboardInterrupt: pass finally: server.server_close() SeatDemoHandler.extension.close() SeatDemoHandler.calibration.close() SeatDemoHandler.repair.close() if __name__ == "__main__": main()