1
0
Files
homelab-public-context/runtime/history/GITEA-READER-ROUTES-AUDIT-289.json
T
2026-07-22 21:23:41 +00:00

31 lines
6.3 KiB
JSON

{
"schema_version": 1,
"channel": "homelab-runtime",
"command_id": "GITEA-READER-ROUTES-AUDIT-289",
"status": "OK",
"rc": 0,
"host": "pve01",
"mode": "read-only",
"component": "cluster-audit",
"started_at_utc": "2026-07-22T21:23:40Z",
"finished_at_utc": "2026-07-22T21:23:40Z",
"reference_register_checked": true,
"reference_sha256": "5763f2f8edc75fcf6f3951f8c95896d1cc112ceccb6cf5b64a383f540a4deb8e",
"error_register_checked": true,
"error_register_sha256": "08b3a769b8e38eaa1acec915352fb328180d70caa7ff6cd9d1ec0da426262752",
"command_sha256": "ca1499ccd79985134e654f663bd829da73f07f8aa2af0a227387a97e6c32c66d",
"duplicate_failed_command_blocked": false,
"block_reason": null,
"execution_started": true,
"changes_made": false,
"sanitized": true,
"secrets_included": false,
"private_addresses_included": false,
"raw_evidence_retained_locally": true,
"raw_evidence_sha256": "8077c2ba090c3c446ffa120fd830682af6b005d086e4263b67ad67eb043d3a9b",
"sanitized_output_sha256": "8077c2ba090c3c446ffa120fd830682af6b005d086e4263b67ad67eb043d3a9b",
"output_truncated_in_json": false,
"full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt",
"output": "PREVIOUS_COMMAND_ID=GITEA-READER-BIND-AUDIT-288\nDETAIL= 1\t#!/usr/bin/python3\nDETAIL= 2\timport hashlib\nDETAIL= 3\timport http.server\nDETAIL= 4\timport json\nDETAIL= 5\timport os\nDETAIL= 6\timport pathlib\nDETAIL= 7\timport re\nDETAIL= 8\timport sys\nDETAIL= 9\t\nDETAIL= 10\tROOT=pathlib.Path(\"/var/lib/homelab-reader-v3\")\nDETAIL= 11\tMANIFEST=ROOT/\"manifest.json\"\nDETAIL= 12\tRESULTS=ROOT/\"results\"\nDETAIL= 13\tCAPABILITY=os.environ[\"HOMELAB_READER_CAPABILITY\"]\nDETAIL= 14\tPORT=int(os.environ.get(\"HOMELAB_READER_PORT\",\"18788\"))\nDETAIL= 15\tRESULT_RE=re.compile(r\"^[A-Za-z0-9][A-Za-z0-9._-]{0,127}-[0-9a-f]{64}\\.txt$\")\nDETAIL= 16\t\nDETAIL= 17\tclass Handler(http.server.BaseHTTPRequestHandler):\nDETAIL= 18\t server_version=\"HomelabReader/3\"\nDETAIL= 19\t\nDETAIL= 20\t def log_message(self,fmt,*args):\nDETAIL= 21\t sys.stderr.write(\"%s - %s\\n\"%(self.address_string(),fmt%args))\nDETAIL= 22\t\nDETAIL= 23\t def reply(self,status,content_type,payload,etag=\"\",include_body=True):\nDETAIL= 24\t self.send_response(status)\nDETAIL= 25\t self.send_header(\"Content-Type\",content_type)\nDETAIL= 26\t self.send_header(\"Content-Length\",str(len(payload)))\nDETAIL= 27\t self.send_header(\"Cache-Control\",\"no-store, no-cache, must-revalidate, max-age=0\")\nDETAIL= 28\t self.send_header(\"Surrogate-Control\",\"no-store\")\nDETAIL= 29\t self.send_header(\"Pragma\",\"no-cache\")\nDETAIL= 30\t self.send_header(\"Expires\",\"0\")\nDETAIL= 31\t self.send_header(\"X-Robots-Tag\",\"noindex, nofollow, noarchive\")\nDETAIL= 32\t if etag:\nDETAIL= 33\t self.send_header(\"ETag\",chr(34)+etag+chr(34))\nDETAIL= 34\t self.send_header(\"X-Homelab-Generation\",etag)\nDETAIL= 35\t self.end_headers()\nDETAIL= 36\t if include_body:\nDETAIL= 37\t self.wfile.write(payload)\nDETAIL= 38\t\nDETAIL= 39\t def do_HEAD(self):\nDETAIL= 40\t self.handle_reader(False)\nDETAIL= 41\t\nDETAIL= 42\t def do_GET(self):\nDETAIL= 43\t self.handle_reader(True)\nDETAIL= 44\t\nDETAIL= 45\t def handle_reader(self,include_body):\nDETAIL= 46\t request_path=self.path.split(\"?\",1)[0]\nDETAIL= 47\t prefix=\"/\"+CAPABILITY+\"/\"\nDETAIL= 48\t if not request_path.startswith(prefix):\nDETAIL= 49\t self.reply(404,\"text/plain; charset=utf-8\",b\"not found\\n\",include_body=include_body)\nDETAIL= 50\t return\nDETAIL= 51\t\nDETAIL= 52\t relative=request_path[len(prefix):]\nDETAIL= 53\t\nDETAIL= 54\t if relative==\"health\":\nDETAIL= 55\t self.reply(200,\"application/json; charset=utf-8\",b\"{\\\"status\\\":\\\"ok\\\",\\\"version\\\":3}\\n\",\"health-v3\",include_body)\nDETAIL= 56\t return\nDETAIL= 57\t\nDETAIL= 58\t if relative==\"feed\":\nDETAIL= 59\t try:\nDETAIL= 60\t payload=MANIFEST.read_bytes()\nDETAIL= 61\t document=json.loads(payload.decode(\"utf-8\"))\nDETAIL= 62\t generation=str(document.get(\"generation\",\"0\"))\nDETAIL= 63\t self.reply(200,\"application/json; charset=utf-8\",payload,generation,include_body)\nDETAIL= 64\t except Exception:\nDETAIL= 65\t self.reply(500,\"text/plain; charset=utf-8\",b\"reader error\\n\",include_body=include_body)\nDETAIL= 66\t return\nDETAIL= 67\t\nDETAIL= 68\t if relative.startswith(\"results/\"):\nDETAIL= 69\t name=relative[len(\"results/\"):]\nDETAIL= 70\t target=RESULTS/name\nDETAIL= 71\t if not RESULT_RE.fullmatch(name) or not target.is_file():\nDETAIL= 72\t self.reply(404,\"text/plain; charset=utf-8\",b\"not found\\n\",include_body=include_body)\nDETAIL= 73\t return\nDETAIL= 74\t try:\nDETAIL= 75\t payload=target.read_bytes()\nDETAIL= 76\t digest=name.rsplit(\"-\",1)[1][:-4]\nDETAIL= 77\t if hashlib.sha256(payload).hexdigest()!=digest:\nDETAIL= 78\t self.reply(500,\"text/plain; charset=utf-8\",b\"integrity error\\n\",include_body=include_body)\nDETAIL= 79\t return\nDETAIL= 80\t self.reply(200,\"text/plain; charset=utf-8\",payload,digest,include_body)\nDETAIL= 81\t except Exception:\nDETAIL= 82\t self.reply(500,\"text/plain; charset=utf-8\",b\"reader error\\n\",include_body=include_body)\nDETAIL= 83\t return\nDETAIL= 84\t\nDETAIL= 85\t self.reply(404,\"text/plain; charset=utf-8\",b\"not found\\n\",include_body=include_body)\nDETAIL= 86\t\nDETAIL= 87\tclass Server(http.server.ThreadingHTTPServer):\nDETAIL= 88\t allow_reuse_address=True\nDETAIL= 89\t\nDETAIL= 90\tServer((\"127.0.0.1\",PORT),Handler).serve_forever()\nCHANGES_MADE=NO\n"
}