{ "schema_version": 1, "channel": "homelab-runtime", "command_id": "RESULT-API-PATCH-AUDIT-20260727T075149Z", "status": "OK", "rc": 0, "host": "pve01", "mode": "verify", "component": "result-integration", "started_at_utc": "2026-07-27T07:52:45Z", "finished_at_utc": "2026-07-27T07:52:45Z", "reference_register_checked": true, "reference_sha256": "5763f2f8edc75fcf6f3951f8c95896d1cc112ceccb6cf5b64a383f540a4deb8e", "error_register_checked": true, "error_register_sha256": "24934a2c7fa5c26f6e828583c4aefac7f143b40c0171736ed7571e617d55ab83", "command_sha256": "b564f92f4324ba19d5c6752e0c53111024fd37092acacc2281d2ab9ac7f39359", "duplicate_failed_command_blocked": false, "block_reason": null, "execution_started": true, "change_declared": false, "result_contract_valid": true, "result_contract_status": null, "result_contract_error": null, "command_rc": 0, "changes_made": false, "rollback_started": false, "rollback_restored": null, "mutation_outcome": "NO_MUTATION", "sanitized": true, "secrets_included": false, "private_addresses_included": false, "raw_evidence_retained_locally": true, "raw_evidence_sha256": "1dabd515e3ddd0d132d8f6cd354770e78207200337dfda97f41dcacb8b3b576d", "sanitized_output_sha256": "1dabd515e3ddd0d132d8f6cd354770e78207200337dfda97f41dcacb8b3b576d", "output_truncated_in_json": false, "full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt", "output": "{\"adapter_functions\":{\"atomic_json\":{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"path\"},{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"value\"}],\"is_async\":false,\"line_end\":238,\"line_start\":202,\"name\":\"atomic_json\"},\"dispatch\":{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"request\"}],\"is_async\":false,\"line_end\":2502,\"line_start\":2419,\"name\":\"dispatch\"},\"load_json\":{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"path\"}],\"is_async\":false,\"line_end\":248,\"line_start\":241,\"name\":\"load_json\"},\"public_state\":{\"arguments\":[{\"has_default\":false,\"kind\":\"keyword_only\",\"name\":\"short_id\"},{\"has_default\":false,\"kind\":\"keyword_only\",\"name\":\"session_token\"},{\"has_default\":false,\"kind\":\"keyword_only\",\"name\":\"client_ip\"}],\"is_async\":false,\"line_end\":1324,\"line_start\":1311,\"name\":\"public_state\"},\"run_command\":{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"args\"},{\"has_default\":true,\"kind\":\"keyword_only\",\"name\":\"timeout\"},{\"has_default\":true,\"kind\":\"keyword_only\",\"name\":\"env\"}],\"is_async\":false,\"line_end\":673,\"line_start\":658,\"name\":\"run_command\"},\"sanitize_state\":{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"state\"}],\"is_async\":false,\"line_end\":1372,\"line_start\":1327,\"name\":\"sanitize_state\"},\"sha256_file\":{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"path\"}],\"is_async\":false,\"line_end\":199,\"line_start\":194,\"name\":\"sha256_file\"},\"state_path\":{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"short_id\"}],\"is_async\":false,\"line_end\":638,\"line_start\":635,\"name\":\"state_path\"},\"worker\":{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"short_id\"}],\"is_async\":false,\"line_end\":2183,\"line_start\":1994,\"name\":\"worker\"}},\"backup_changed\":false,\"changes_made\":false,\"checks\":{\"adapter_functions_complete\":true,\"adapter_healthy\":true,\"adapter_sha\":true,\"current_running_once\":true,\"no_invalid_states\":true,\"no_other_running\":true,\"portal_functions_complete\":true,\"portal_handler_do_get_present\":true,\"portal_handler_present\":true,\"portal_handler_reply_present\":true,\"portal_healthy\":true,\"portal_sha\":true,\"runner_sha\":true,\"source_excerpts_sanitized\":true},\"cluster_changed\":false,\"command_id\":\"RESULT-API-PATCH-AUDIT-20260727T075149Z\",\"gitea_changed\":false,\"plan_contract\":{\"adapter_operations\":[\"result_public\",\"result_public_key\"],\"create\":[\"/var/lib/homelab-command-adapter/result-signing/private.pem\",\"/var/lib/homelab-command-adapter/result-signing/public.pem\"],\"modify\":[\"/usr/local/sbin/homelab-command-adapter\",\"/usr/local/sbin/homelab-command-portal\"],\"preserve\":[\"/usr/local/sbin/homelab-chat-run\",\"existing state files\",\"existing evidence objects\",\"backup\",\"cluster\",\"Gitea history\"],\"public_routes\":[\"/.well-known/homelab-result//.json\",\"/.well-known/homelab-result-key.pem\"]},\"portal_classes\":{\"Handler\":{\"line_end\":892,\"line_start\":451,\"methods\":[{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"self\"},{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"fmt\"},{\"has_default\":false,\"kind\":\"var_positional\",\"name\":\"args\"}],\"is_async\":false,\"line_end\":469,\"line_start\":455,\"name\":\"log_message\"},{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"self\"},{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"status\"},{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"content_type\"},{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"body\"},{\"has_default\":true,\"kind\":\"keyword_only\",\"name\":\"headers\"}],\"is_async\":false,\"line_end\":504,\"line_start\":471,\"name\":\"reply\"},{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"self\"},{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"location\"},{\"has_default\":true,\"kind\":\"keyword_only\",\"name\":\"headers\"}],\"is_async\":false,\"line_end\":519,\"line_start\":506,\"name\":\"redirect\"},{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"self\"},{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"status\"},{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"message\"}],\"is_async\":false,\"line_end\":529,\"line_start\":521,\"name\":\"error_reply\"},{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"self\"}],\"is_async\":false,\"line_end\":535,\"line_start\":531,\"name\":\"content_length\"},{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"self\"},{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"limit\"}],\"is_async\":false,\"line_end\":544,\"line_start\":537,\"name\":\"read_body\"},{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"self\"}],\"is_async\":false,\"line_end\":551,\"line_start\":546,\"name\":\"path_parts\"},{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"self\"}],\"is_async\":false,\"line_end\":749,\"line_start\":553,\"name\":\"do_GET\"},{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"self\"}],\"is_async\":false,\"line_end\":892,\"line_start\":751,\"name\":\"do_POST\"}],\"name\":\"Handler\"}},\"portal_functions\":{\"adapter_call\":{\"arguments\":[{\"has_default\":false,\"kind\":\"positional_or_keyword\",\"name\":\"request\"}],\"is_async\":false,\"line_end\":91,\"line_start\":44,\"name\":\"adapter_call\"}},\"private_addresses_included\":false,\"rollback_started\":false,\"sanitized\":true,\"schema\":1,\"secrets_included\":false,\"service_files\":{\"adapter\":\"[Unit]\\nDescription=Homelab command adapter\\nAfter=network-online.target\\nWants=network-online.target\\n\\n[Service]\\nType=simple\\nExecStart=/usr/bin/python3 -B /usr/local/sbin/homelab-command-adapter --serve\\nUser=root\\nGroup=homelab-command-portal\\nUMask=0027\\nRuntimeDirectory=homelab-command-adapter\\nRuntimeDirectoryMode=0750\\nRestart=on-failure\\nRestartSec=2\\nNoNewPrivileges=false\\nPrivateTmp=true\\nProtectClock=true\\nProtectControlGroups=true\\nProtectKernelLogs=true\\nProtectKernelModules=true\\nProtectKernelTunables=true\\nRestrictRealtime=true\\nLockPersonality=true\\nMemoryDenyWriteExecute=true\\nSystemCallArchitectures=native\\nTimeoutStopSec=15\\n\\n[Install]\\nWantedBy=multi-user.target\\n\",\"portal\":\"[Unit]\\nDescription=Homelab command portal\\nAfter=network-online.target homelab-command-adapter.service\\nRequires=homelab-command-adapter.service\\nWants=network-online.target\\nStartLimitIntervalSec=30\\nStartLimitBurst=3\\n\\n[Service]\\nType=simple\\nExecStartPre=/usr/bin/python3 -B /usr/local/sbin/homelab-command-portal --self-test\\nExecStart=/usr/bin/python3 -B /usr/local/sbin/homelab-command-portal\\nUser=homelab-command-portal\\nGroup=homelab-command-portal\\nUMask=0077\\nRestart=on-failure\\nRestartSec=2\\nNoNewPrivileges=true\\nPrivateTmp=true\\nPrivateDevices=true\\nProtectSystem=strict\\nProtectHome=true\\nReadWritePaths=/var/lib/homelab-command-portal\\nProtectClock=true\\nProtectControlGroups=true\\nProtectKernelLogs=true\\nProtectKernelModules=true\\nProtectKernelTunables=true\\nRestrictSUIDSGID=true\\nRestrictRealtime=true\\nLockPersonality=true\\nMemoryDenyWriteExecute=true\\nRestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX\\nSystemCallArchitectures=native\\nTimeoutStopSec=15\\n\\n[Install]\\nWantedBy=multi-user.target\\n\"},\"services\":{\"adapter\":{\"active\":\"active\",\"pid\":\"976008\",\"restarts\":\"0\",\"sub\":\"running\"},\"portal\":{\"active\":\"active\",\"pid\":\"976035\",\"restarts\":\"0\",\"sub\":\"running\"}},\"source_excerpts\":{\"adapter_dispatch\":\"2414: \\\"ok\\\": True,\\n2415: \\\"result\\\": value,\\n2416: }\\n2417: \\n2418: \\n2419: def dispatch(request: dict[str, Any]) -> dict[str, Any]:\\n2420: operation = request.get(\\\"op\\\")\\n2421: if operation == \\\"health\\\":\\n2422: return response_ok(\\n2423: {\\n2424: \\\"status\\\": \\\"ok\\\",\\n2425: \\\"version\\\": 1,\\n2426: }\\n2427: )\\n2428: if operation == \\\"bind_enrollment\\\":\\n2429: return response_ok(\\n2430: bind_enrollment(\\n2431: str(request.get(\\\"token\\\", \\\"\\\")),\\n2432: str(request.get(\\\"client_ip\\\", \\\"\\\")),\\n2433: )\\n2434: )\\n2435: if operation == \\\"enroll\\\":\\n2436: return response_ok(\\n2437: enroll_device(\\n2438: str(request.get(\\\"token\\\", \\\"\\\")),\\n2439: str(request.get(\\\"client_ip\\\", \\\"\\\")),\\n2440: )\\n2441: )\\n2442: if operation == \\\"import\\\":\\n2443: return response_ok(\\n2444: import_capsule(\\n2445: device_token=[REDACTED]\\n2446: request.get(\\\"device_token\\\", \\\"\\\")\\n2447: ),\\n2448: client_ip=str(\\n2449: request.get(\\\"client_ip\\\", \\\"\\\")\\n2450: ),\\n2451: upload_path=str(\\n2452: request.get(\\\"upload_path\\\", \\\"\\\")\\n2453: ),\\n2454: )\\n2455: )\\n2456: if operation == \\\"consume_bootstrap\\\":\\n2457: return response_ok(\\n2458: consume_bootstrap(\\n2459: short_id=str(request.get(\\\"short_id\\\", \\\"\\\")),\\n2460: token=[REDACTED]\\\"token\\\", \\\"\\\")),\\n2461: client_ip=str(\\n2462: request.get(\\\"client_ip\\\", \\\"\\\")\\n2463: ),\\n2464: )\\n2465: )\\n2466: if operation == \\\"state\\\":\\n2467: return response_ok(\\n2468: public_state(\\n2469: short_id=str(request.get(\\\"short_id\\\", \\\"\\\")),\\n2470: session_token=[REDACTED]\\n2471: request.get(\\\"session_token\\\", \\\"\\\")\\n2472: ),\\n2473: client_ip=str(\\n2474: request.get(\\\"client_ip\\\", \\\"\\\")\\n2475: ),\\n2476: )\\n2477: )\\n2478: if operation == \\\"execute\\\":\\n2479: return response_ok(\\n2480: start_execution(\\n2481: short_id=str(request.get(\\\"short_id\\\", \\\"\\\")),\\n2482: session_token=[REDACTED]\\n2483: request.get(\\\"session_token\\\", \\\"\\\")\\n2484: ),\\n2485: client_ip=str(\\n2486: request.get(\\\"client_ip\\\", \\\"\\\")\\n2487: ),\\n2488: )\\n2489: )\\n2490: if operation == \\\"evidence_url\\\":\\n2491: return response_ok(\\n2492: evidence_url(\\n2493: short_id=str(request.get(\\\"short_id\\\", \\\"\\\")),\\n2494: session_token=[REDACTED]\\n2495: request.get(\\\"session_token\\\", \\\"\\\")\\n2496: ),\\n2497: client_ip=str(\\n2498: request.get(\\\"client_ip\\\", \\\"\\\")\\n2499: ),\\n2500: )\\n2501: )\\n2502: raise AdapterError(\\\"unsupported operation\\\")\\n2503: \\n2504: \\n2505: class Handler(socketserver.StreamRequestHandler):\\n2506: def handle(self) -> None:\\n2507: credentials = self.request.getsockopt(\",\"adapter_public_state\":\"1306: ):\\n1307: return session\\n1308: raise AdapterError(\\\"session authorization failed\\\")\\n1309: \\n1310: \\n1311: def public_state(\\n1312: *,\\n1313: short_id: str,\\n1314: session_token: [REDACTED]\\n1315: client_ip: str,\\n1316: ) -> dict[str, Any]:\\n1317: with GlobalLock():\\n1318: state = load_json(state_path(short_id))\\n1319: authorize_session(\\n1320: state,\\n1321: session_token=[REDACTED]\\n1322: client_ip=client_ip,\\n1323: )\\n1324: return sanitize_state(state)\\n1325: \\n1326: \\n1327: def sanitize_state(state: dict[str, Any]) -> dict[str, Any]:\\n1328: execution = state.get(\\\"execution\\\")\\n1329: public_execution = None\",\"adapter_sanitize_state\":\"1322: client_ip=client_ip,\\n1323: )\\n1324: return sanitize_state(state)\\n1325: \\n1326: \\n1327: def sanitize_state(state: dict[str, Any]) -> dict[str, Any]:\\n1328: execution = state.get(\\\"execution\\\")\\n1329: public_execution = None\\n1330: if isinstance(execution, dict):\\n1331: public_execution = {\\n1332: key: execution.get(key)\\n1333: for key in (\\n1334: \\\"started_at_utc\\\",\\n1335: \\\"finished_at_utc\\\",\\n1336: \\\"runner_rc\\\",\\n1337: \\\"runner_document_rc\\\",\\n1338: \\\"runner_status\\\",\\n1339: \\\"runner_wrapper_matches_document\\\",\\n1340: \\\"runner_json_sha256\\\",\\n1341: \\\"runner_text_sha256\\\",\\n1342: )\\n1343: if key in execution\\n1344: }\\n1345: \\n1346: evidence = state.get(\\\"evidence\\\")\\n1347: public_evidence = None\\n1348: if isinstance(evidence, dict):\\n1349: public_evidence = {\\n1350: key: evidence.get(key)\\n1351: for key in (\\n1352: \\\"object_key\\\",\\n1353: \\\"sha256\\\",\\n1354: \\\"bytes\\\",\\n1355: \\\"gateway_verified\\\",\\n1356: )\\n1357: if key in evidence\\n1358: }\\n1359: \\n1360: return {\\n1361: \\\"schema_version\\\": 1,\\n1362: \\\"short_id\\\": state[\\\"short_id\\\"],\\n1363: \\\"capsule_sha256\\\": state[\\\"capsule_sha256\\\"],\\n1364: \\\"capsule_bytes\\\": state[\\\"capsule_bytes\\\"],\\n1365: \\\"manifest\\\": state[\\\"manifest\\\"],\\n1366: \\\"imported_at_utc\\\": state[\\\"imported_at_utc\\\"],\\n1367: \\\"command_object\\\": state[\\\"command_object\\\"],\\n1368: \\\"status\\\": state[\\\"status\\\"],\\n1369: \\\"execution\\\": public_execution,\\n1370: \\\"evidence\\\": public_evidence,\\n1371: \\\"error\\\": state.get(\\\"error\\\"),\\n1372: }\\n1373: \\n1374: \\n1375: def start_execution(\\n1376: *,\\n1377: short_id: str,\",\"adapter_worker_finalization\":\"2058: state[\\\"manifest\\\"][\\\"command_id\\\"],\\n2059: started_epoch,\\n2060: )\\n2061: runner_document = load_json(runner_json)\\n2062: \\n2063: bundle, evidence_sha, evidence_bytes = (\\n2064: create_evidence_bundle(\\n2065: state=state,\\n2066: runner_json=runner_json,\\n2067: runner_txt=runner_txt,\\n2068: )\\n2069: )\\n2070: prefix = (\\n2071: \\\"portal-tests\\\"\\n2072: if state[\\\"manifest\\\"][\\\"component\\\"]\\n2073: == \\\"command-portal-smoke\\\"\\n2074: else \\\"portal\\\"\\n2075: )\\n2076: object_key = (\\n2077: f\\\"{prefix}/\\\"\\n2078: f\\\"{state['manifest']['command_id']}/\\\"\\n2079: f\\\"{state['capsule_sha256']}/\\\"\\n2080: \\\"evidence.tgz\\\"\\n2081: )\\n2082: upload_evidence(\\n2083: bundle,\\n2084: object_key,\\n2085: evidence_sha,\\n2086: )\\n2087: \\n2088: with GlobalLock():\\n2089: current = load_json(path)\\n2090: if not worker_state_owned(\\n2091: current,\\n2092: os.getpid(),\\n2093: ):\\n2094: raise AdapterError(\\n2095: \\\"worker finalization ownership lost\\\"\\n2096: )\\n2097: document_status = str(\\n2098: runner_document.get(\\\"status\\\", \\\"FAIL\\\")\\n2099: )\\n2100: try:\\n2101: document_rc = int(runner_document[\\\"rc\\\"])\\n2102: except (KeyError, TypeError, ValueError) as exc:\\n2103: raise AdapterError(\\\"runner artifact rc invalid\\\") from exc\\n2104: wrapper_matches = result.returncode == document_rc\\n2105: current[\\\"status\\\"] = (\\n2106: document_status if wrapper_matches else \\\"FAIL\\\"\\n2107: )\\n2108: current[\\\"execution\\\"].update(\\n2109: {\\n2110: \\\"finished_at_utc\\\": iso(),\\n2111: \\\"runner_rc\\\": result.returncode,\\n2112: \\\"runner_document_rc\\\": document_rc,\\n2113: \\\"runner_status\\\": document_status,\\n2114: \\\"runner_wrapper_matches_document\\\": wrapper_matches,\\n2115: \\\"runner_json\\\": str(runner_json),\\n2116: \\\"runner_text\\\": str(runner_txt),\\n2117: \\\"runner_json_sha256\\\": sha256_file(\\n2118: runner_json\\n2119: ),\\n2120: \\\"runner_text_sha256\\\": sha256_file(\\n2121: runner_txt\\n2122: ),\\n2123: }\\n2124: )\\n2125: current[\\\"evidence\\\"] = {\\n2126: \\\"object_key\\\": object_key,\\n2127: \\\"sha256\\\": evidence_sha,\\n2128: \\\"bytes\\\": evidence_bytes,\\n2129: \\\"local_bundle\\\": str(bundle),\\n2130: \\\"gateway_verified\\\": True,\\n2131: }\\n2132: current[\\\"error\\\"] = (\\n2133: None\\n2134: if wrapper_matches\\n2135: else {\\n2136: \\\"type\\\": \\\"RunnerWrapperMismatch\\\",\\n2137: \\\"message\\\": (\\n2138: \\\"existing runner returned a different rc \\\"\\n2139: \\\"after writing its public artifact; \\\"\\n2140: \\\"runtime publication or wrapper completion failed\\\"\\n2141: ),\\n2142: }\\n2143: )\\n2144: atomic_json(path, current)\\n2145: return 0\\n2146: \\n2147: except Exception as exc:\\n2148: try:\\n2149: with wrapper_log.open(\\n2150: \\\"a\\\",\\n2151: encoding=\\\"utf-8\\\",\\n2152: errors=\\\"replace\\\",\\n2153: ) as stream:\\n2154: stream.write(\\n2155: f\\\"WORKER_ERROR={type(exc).__name__}:{exc}\\\\\\\\n\\\"\\n2156: )\\n2157: os.chmod(wrapper_log, 0o640)\\n2158: except Exception:\\n2159: pass\\n2160: \\n2161: with GlobalLock():\\n2162: try:\\n2163: current = load_json(path)\\n2164: if worker_state_owned(\\n2165: current,\\n2166: os.getpid(),\\n2167: ):\\n2168: current[\\\"status\\\"] = \\\"FAIL\\\"\\n2169: if isinstance(\\n2170: current.get(\\\"execution\\\"),\\n2171: dict,\\n2172: ):\\n2173: current[\\\"execution\\\"][\\n2174: \\\"finished_at_utc\\\"\\n2175: ] = iso()\\n2176: current[\\\"error\\\"] = {\\n2177: \\\"type\\\": type(exc).__name__,\\n2178: \\\"message\\\": str(exc)[:4000],\\n2179: }\\n2180: atomic_json(path, current)\\n2181: except Exception:\\n2182: pass\\n2183: return 1\",\"portal_Handler_do_GET\":\"550: keep_blank_values=True,\\n551: )\\n552: \\n553: def do_GET(self) -> None:\\n554: try:\\n555: path, query = self.path_parts()\\n556: \\n557: if path == \\\"/healthz\\\":\\n558: parse_client(self, allow_local_health=True)\\n559: result = adapter_call({\\\"op\\\": \\\"health\\\"})\\n560: body = (\\n561: json.dumps(\\n562: {\\n563: \\\"status\\\": \\\"ok\\\",\\n564: \\\"version\\\": 1,\\n565: \\\"adapter\\\": result[\\\"status\\\"],\\n566: },\\n567: separators=(\\\",\\\", \\\":\\\"),\\n568: sort_keys=True,\\n569: )\\n570: + \\\"\\\\n\\\"\\n571: ).encode()\\n572: self.reply(\\n573: 200,\\n574: \\\"application/json; charset=utf-8\\\",\\n575: body,\\n576: )\\n577: return\\n578: \\n579: client_ip = parse_client(self)\\n580: \\n581: if path == \\\"/bridge/bridge.cmd\\\":\\n582: self.reply(\\n583: 200,\\n584: \\\"application/octet-stream\\\",\\n585: BRIDGE_CMD.encode(\\\"utf-8\\\"),\\n586: headers={\\n587: \\\"Content-Disposition\\\": (\\n588: 'attachment; filename=\\\"bridge.cmd\\\"'\\n589: )\\n590: },\\n591: )\\n592: return\\n593: \\n594: if path.startswith(\\\"/enroll/\\\"):\\n595: relative = path[len(\\\"/enroll/\\\") :]\\n596: if relative.endswith(\\\"/bridge-setup.cmd\\\"):\\n597: token = [REDACTED]\\n598: : -len(\\\"/bridge-setup.cmd\\\")\\n599: ]\\n600: adapter_call(\\n601: {\\n602: \\\"op\\\": \\\"bind_enrollment\\\",\\n603: \\\"token\\\": token,\\n604: \\\"client_ip\\\": client_ip,\\n605: }\\n606: )\\n607: self.reply(\\n608: 200,\\n609: \\\"application/octet-stream\\\",\\n610: setup_script(token),\\n611: headers={\\n612: \\\"Content-Disposition\\\": (\\n613: 'attachment; '\\n614: 'filename=\\\"HomelabBridgeSetup.cmd\\\"'\\n615: )\\n616: },\\n617: )\\n618: return\\n619: \\n620: token = [REDACTED]\\n621: info = adapter_call(\\n622: {\\n623: \\\"op\\\": \\\"bind_enrollment\\\",\\n624: \\\"token\\\": token,\\n625: \\\"client_ip\\\": client_ip,\\n626: }\\n627: )\\n628: body = f\\\"\\\"\\\"\\n629: \\n630: \\n631: Homelab Bridge\\n632: \\n633: \\n634:

Установка Homelab Bridge

\\n635:

Профиль: {html.escape(str(info['label']))}

\\n636:

Ссылка одноразовая и уже привязана к этому NetBird-адресу.

\\n637:

Скачать установщик

\\n638:

После запуска установщика файлы .hcmd будут открываться двойным кликом.

\\n639: \\\"\\\"\\\".encode()\\n640: self.reply(\\n641: 200,\\n642: \\\"text/html; charset=utf-8\\\",\\n643: body,\\n644: )\\n645: return\\n646: \\n647: match = re.fullmatch(\\n648: r\\\"/r/([A-Z2-7]{10,20})\\\",\\n649: path,\\n650: )\\n651: if match:\\n652: short_id = safe_short(match.group(1))\\n653: token_values = query.get(\\\"t\\\", [])\\n654: if token_values:\\n655: token = [REDACTED]\\n656: session = adapter_call(\\n657: {\\n658: \\\"op\\\": \\\"consume_bootstrap\\\",\\n659: \\\"short_id\\\": short_id,\\n660: \\\"token\\\": token,\\n661: \\\"client_ip\\\": client_ip,\\n662: }\\n663: )\\n664: cookie = (\\n665: f\\\"__Host-HLSESSION={session['session_token']}; \\\"\\n666: f\\\"Max-Age={8 * 3600}; Path=/; \\\"\\n667: \\\"Secure; HttpOnly; SameSite=Strict\\\"\\n668: )\\n669: self.redirect(\\n670: f\\\"/r/{short_id}\\\",\\n671: headers={\\\"Set-Cookie\\\": cookie},\\n672: )\\n673: return\\n674: \\n675: session_token = [REDACTED]\\n676: state = adapter_call(\\n677: {\\n678: \\\"op\\\": \\\"state\\\",\\n679: \\\"short_id\\\": short_id,\\n680: \\\"session_token\\\": session_token,\\n681: \\\"client_ip\\\": client_ip,\\n682: }\\n683: )\\n684: self.reply(\\n685: 200,\\n686: \\\"text/html; charset=utf-8\\\",\\n687: render_card(state, session_token),\\n688: )\\n689: return\\n690: \\n691: evidence_match = re.fullmatch(\\n692: r\\\"/r/([A-Z2-7]{10,20})/evidence\\\",\\n693: path,\\n694: )\\n695: if evidence_match:\\n696: short_id = safe_short(\\n697: evidence_match.group(1)\\n698: )\\n699: signed = adapter_call(\\n700: {\\n701: \\\"op\\\": \\\"evidence_url\\\",\\n702: \\\"short_id\\\": short_id,\\n703: \\\"session_token\\\": cookie_session(self),\\n704: \\\"client_ip\\\": client_ip,\\n705: }\\n706: )\\n707: self.redirect(str(signed[\\\"url\\\"]))\\n708: return\\n709: \\n710: state_match = re.fullmatch(\\n711: r\\\"/api/state/([A-Z2-7]{10,20})\\\",\\n712: path,\\n713: )\\n714: if state_match:\\n715: short_id = safe_short(\\n716: state_match.group(1)\\n717: )\\n718: state = adapter_call(\\n719: {\\n720: \\\"op\\\": \\\"state\\\",\\n721: \\\"short_id\\\": short_id,\\n722: \\\"session_token\\\": cookie_session(self),\\n723: \\\"client_ip\\\": client_ip,\\n724: }\\n725: )\\n726: self.reply(\\n727: 200,\\n728: \\\"application/json; charset=utf-8\\\",\\n729: (\\n730: json.dumps(\\n731: state,\\n732: ensure_ascii=False,\\n733: separators=(\\\",\\\", \\\":\\\"),\\n734: sort_keys=True,\\n735: )\\n736: + \\\"\\\\n\\\"\\n737: ).encode(),\\n738: )\\n739: return\\n740: \\n741: self.error_reply(404, \\\"not found\\\")\\n742: \\n743: except PortalError as exc:\\n744: self.error_reply(403, str(exc))\\n745: except Exception as exc:\\n746: self.error_reply(\\n747: 500,\\n748: f\\\"{type(exc).__name__}:{str(exc)[:1000]}\\\",\\n749: )\\n750: \\n751: def do_POST(self) -> None:\\n752: try:\",\"portal_Handler_error_reply\":\"518: headers=values,\\n519: )\\n520: \\n521: def error_reply(self, status: int, message: str) -> None:\\n522: body = (\\n523: f\\\"PORTAL_ERROR={html.escape(message)}\\\\n\\\"\\n524: ).encode()\\n525: self.reply(\\n526: status,\\n527: \\\"text/plain; charset=utf-8\\\",\\n528: body,\\n529: )\\n530: \\n531: def content_length(self) -> int:\\n532: raw = self.headers.get(\\\"Content-Length\\\")\",\"portal_Handler_path_parts\":\"543: raise PortalError(\\\"short request body\\\")\\n544: return body\\n545: \\n546: def path_parts(self) -> tuple[str, dict[str, list[str]]]:\\n547: parsed = urllib.parse.urlsplit(self.path)\\n548: return parsed.path, urllib.parse.parse_qs(\\n549: parsed.query,\\n550: keep_blank_values=True,\\n551: )\\n552: \\n553: def do_GET(self) -> None:\\n554: try:\",\"portal_Handler_reply\":\"468: f\\\"{self.client_address[0]} - {message}\\\\n\\\"\\n469: )\\n470: \\n471: def reply(\\n472: self,\\n473: status: int,\\n474: content_type: str,\\n475: body: bytes,\\n476: *,\\n477: headers: dict[str, str] | None = None,\\n478: ) -> None:\\n479: self.send_response(status)\\n480: self.send_header(\\\"Content-Type\\\", content_type)\\n481: self.send_header(\\\"Content-Length\\\", str(len(body)))\\n482: self.send_header(\\n483: \\\"Cache-Control\\\",\\n484: \\\"no-store, no-cache, must-revalidate, max-age=0\\\",\\n485: )\\n486: self.send_header(\\\"Pragma\\\", \\\"no-cache\\\")\\n487: self.send_header(\\\"Expires\\\", \\\"0\\\")\\n488: self.send_header(\\n489: \\\"X-Robots-Tag\\\",\\n490: \\\"noindex, nofollow,noarchive\\\",\\n491: )\\n492: self.send_header(\\\"X-Content-Type-Options\\\", \\\"nosniff\\\")\\n493: self.send_header(\\\"Referrer-Policy\\\", \\\"no-referrer\\\")\\n494: self.send_header(\\n495: \\\"Content-Security-Policy\\\",\\n496: \\\"default-src 'none'; style-src 'unsafe-inline'; \\\"\\n497: \\\"form-action 'self'; frame-ancestors 'none'; \\\"\\n498: \\\"base-uri 'none'\\\",\\n499: )\\n500: for key, value in (headers or {}).items():\\n501: self.send_header(key, value)\\n502: self.end_headers()\\n503: if body:\\n504: self.wfile.write(body)\\n505: \\n506: def redirect(\\n507: self,\"},\"source_sha256\":{\"adapter\":\"8d0af84dcfcf6ddbfd1c4e6cbb059cef66b4cfc6c75bfd66da649acc229c7f5e\",\"portal\":\"8056faf4ef6348f0b06319ad3c49fbfeeadf25b6370f857ea19569bd27652ee2\",\"runner\":\"b248a4c32c9cc64e5747e7dce6c7fc0a23f5124a77c71ce72e27a81aceae9d2d\"},\"states\":{\"current_running\":[{\"command_id\":\"RESULT-API-PATCH-AUDIT-20260727T075149Z\",\"state_file\":\"275ZUEB6ZH.json\"}],\"invalid\":[],\"other_running\":[]},\"status\":\"OK\"}\n" }