1
0
Files
homelab-public-context/runtime/latest.json
T
2026-07-22 07:56:07 +00:00

31 lines
10 KiB
JSON

{
"schema_version": 1,
"channel": "homelab-runtime",
"command_id": "CLUSTER-REFERENCE-MODE-SEMANTICS-153",
"status": "OK",
"rc": 0,
"host": "pve01",
"mode": "read-only",
"component": "cluster-audit",
"started_at_utc": "2026-07-22T07:56:06Z",
"finished_at_utc": "2026-07-22T07:56:06Z",
"reference_register_checked": true,
"reference_sha256": "5763f2f8edc75fcf6f3951f8c95896d1cc112ceccb6cf5b64a383f540a4deb8e",
"error_register_checked": true,
"error_register_sha256": "08b3a769b8e38eaa1acec915352fb328180d70caa7ff6cd9d1ec0da426262752",
"command_sha256": "8dc27e444049919a8436dfda6dbbf1e6f925075388cb73ecf483b2944f0dcf2e",
"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": "5a67f7767c4daff72ce91f626619b8d4251dbd9378ec9d757183506a3e9345d0",
"sanitized_output_sha256": "1d71af6fb931c9d83bc82e594516212e45cd585f292d30486e0939ba5708acd0",
"output_truncated_in_json": false,
"full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt",
"output": "PREVIOUS_RESULT=VERIFIED\nPREVIOUS_IMMUTABLE_COMMIT=fa3878ea8aeec87002c4c8f179fb88e25184e924\n=== RUNNER_HELP ===\nUsage:\n homelab-chat-run COMMAND_ID MODE COMPONENT -- command [arguments...]\n\nMODE:\n read-only\n verify\n change\n transport-test\n\nEnvironment:\n HOMELAB_ALLOW_REPEAT=1 Allow exact repeat of a previously failed command.\n HOMELAB_TIMEOUT=SECONDS Optional command timeout.\n=== MODE_VALIDATION_AND_EFFECTS ===\n1-#!/usr/bin/env bash\n2-set -Eeuo pipefail\n3-umask 077\n4-\n5-usage() {\n6- cat >&2 <<'USAGE'\n7-Usage:\n8- homelab-chat-run COMMAND_ID MODE COMPONENT -- command [arguments...]\n9-\n10-MODE:\n11: read-only\n12: verify\n13: change\n14: transport-test\n15-\n16-Environment:\n17- HOMELAB_ALLOW_REPEAT=1 Allow exact repeat of a previously failed command.\n18- HOMELAB_TIMEOUT=SECONDS Optional command timeout.\n19-USAGE\n20- exit 64\n21-}\n22-\n23-[ \"$#\" -ge 5 ] || usage\n24-\n25-COMMAND_ID=\"$1\"\n26-MODE=\"$2\"\n27-COMPONENT=\"$3\"\n28-shift 3\n29-\n30-[ \"${1:-}\" = '--' ] || usage\n31-shift\n32-[ \"$#\" -ge 1 ] || usage\n33-\n34-case \"$COMMAND_ID\" in\n35- ''|*[!A-Za-z0-9._-]*)\n36- echo 'RESULT=FAIL'\n37- echo 'REASON=INVALID_COMMAND_ID'\n38- exit 65\n39- ;;\n40-esac\n41-\n42-case \"$COMPONENT\" in\n43- ''|*[!A-Za-z0-9._-]*)\n44- echo 'RESULT=FAIL'\n45- echo 'REASON=INVALID_COMPONENT'\n46- exit 66\n47- ;;\n48-esac\n49-\n50:case \"$MODE\" in\n51: read-only|verify|change|transport-test)\n52- ;;\n53- *)\n54- echo 'RESULT=FAIL'\n55: echo 'REASON=INVALID_MODE'\n56- exit 67\n57- ;;\n58-esac\n59-\n60-for TOOL in \\\n61- awk \\\n62- curl \\\n63- flock \\\n64- python3 \\\n65- scp \\\n66- sha256sum \\\n67- ssh\n68-do\n69- command -v \"$TOOL\" >/dev/null 2>&1 || {\n70- echo 'RESULT=FAIL'\n71- echo \"REASON=REQUIRED_TOOL_MISSING:$TOOL\"\n72- exit 68\n73- }\n74-done\n75-\n76-REFERENCE=/etc/pve/31_HOMELAB_REFERENCE.md\n77-ERROR_REGISTER=/etc/pve/HOMELAB_ASSISTANT_ERROR_REGISTER.md\n78-\n79-[ -r \"$REFERENCE\" ] || {\n80- echo 'RESULT=FAIL'\n81- echo 'REASON=REFERENCE_NOT_READABLE'\n82- exit 69\n83-}\n84-\n85-[ -r \"$ERROR_REGISTER\" ] || {\n86- echo 'RESULT=FAIL'\n87- echo 'REASON=ERROR_REGISTER_NOT_READABLE'\n88- exit 70\n89-}\n90-\n91-STATE_DIR=/var/lib/homelab-chat-run\n92-RAW_DIR=\"$STATE_DIR/raw\"\n93-PUBLIC_DIR=\"$STATE_DIR/public\"\n94-LEDGER=\"$STATE_DIR/state/command-ledger.tsv\"\n95-LOCK=\"$STATE_DIR/state/runner.lock\"\n--\n131-\n132-PREVIOUS_FAILED_RC=\"$(\n133- awk -F '\\t' -v hash=\"$COMMAND_SHA256\" '\n134- $3 == hash && $4 != \"0\" {\n135- value=$4\n136- }\n137-\n138- END {\n139- print value\n140- }\n141- ' \"$LEDGER\"\n142-)\"\n143-\n144-RUN_STARTED=true\n145-REPEAT_BLOCKED=false\n146:BLOCK_REASON=''\n147:CHANGES_MADE=false\n148-\n149:case \"$MODE\" in\n150: change)\n151: CHANGES_MADE=true\n152- ;;\n153-esac\n154-\n155-if [ -n \"$PREVIOUS_FAILED_RC\" ] &&\n156- [ \"${HOMELAB_ALLOW_REPEAT:-0}\" != 1 ]; then\n157-\n158- RUN_STARTED=false\n159- REPEAT_BLOCKED=true\n160: BLOCK_REASON='EXACT_FAILED_COMMAND_REPEAT'\n161- RC=73\n162- STATUS='BLOCKED'\n163-\n164- {\n165- echo 'COMMAND_EXECUTION_BLOCKED=yes'\n166- echo 'REASON=EXACT_FAILED_COMMAND_REPEAT'\n167- echo \"PREVIOUS_RC=$PREVIOUS_FAILED_RC\"\n168- echo \"COMMAND_SHA256=$COMMAND_SHA256\"\n169- echo\n170- echo 'Set HOMELAB_ALLOW_REPEAT=1 only after reviewing the previous failure.'\n171- } >\"$RAW_FILE\"\n172-else\n173- set +e\n174-\n175- if [ -n \"${HOMELAB_TIMEOUT:-}\" ]; then\n176- case \"$HOMELAB_TIMEOUT\" in\n177- *[!0-9]*|'')\n178- echo 'RESULT=FAIL'\n179- echo 'REASON=INVALID_HOMELAB_TIMEOUT'\n180- exit 74\n181- ;;\n182- esac\n183-\n184- timeout \\\n185- --foreground \\\n186- --preserve-status \\\n187- \"$HOMELAB_TIMEOUT\" \\\n188- \"$@\" >\"$RAW_FILE\" 2>&1\n189- RC=$?\n190- else\n191- \"$@\" >\"$RAW_FILE\" 2>&1\n192- RC=$?\n193- fi\n194-\n195- set -e\n196-\n197- if [ \"$RC\" -eq 0 ]; then\n198- STATUS='OK'\n199- else\n200- STATUS='FAIL'\n--\n317- \"$COMMAND_ID\" \\\n318- \"$STATUS\" \\\n319- \"$RC\" \\\n320- \"$HOST_SHORT\" \\\n321- \"$MODE\" \\\n322- \"$COMPONENT\" \\\n323- \"$STARTED_AT\" \\\n324- \"$FINISHED_AT\" \\\n325- \"$REFERENCE_SHA256\" \\\n326- \"$ERROR_REGISTER_SHA256\" \\\n327- \"$COMMAND_SHA256\" \\\n328- \"$RAW_SHA256\" \\\n329- \"$SANITIZED_SHA256\" \\\n330- \"$RUN_STARTED\" \\\n331- \"$REPEAT_BLOCKED\" \\\n332: \"$BLOCK_REASON\" \\\n333: \"$CHANGES_MADE\" <<'PY'\n334-import json\n335-import sys\n336-from pathlib import Path\n337-\n338-(\n339- json_path,\n340- output_path,\n341- command_id,\n342- status,\n343- rc,\n344- host,\n345- mode,\n346- component,\n347- started,\n348- finished,\n349- reference_sha,\n350- error_sha,\n351- command_sha,\n352- raw_sha,\n353- sanitized_sha,\n354- run_started,\n355- repeat_blocked,\n356: block_reason,\n357: changes_made,\n358-) = sys.argv[1:]\n359-\n360-output = Path(output_path).read_text(\n361- encoding=\"utf-8\",\n362- errors=\"replace\",\n363-)\n364-\n365-encoded = output.encode(\"utf-8\")\n366-json_limit = 300_000\n367-output_truncated = len(encoded) > json_limit\n368-\n369-if output_truncated:\n370- output_preview = encoded[:json_limit].decode(\n371- \"utf-8\",\n372- errors=\"ignore\",\n373- )\n374-else:\n375- output_preview = output\n376-\n377-document = {\n378- \"schema_version\": 1,\n379- \"channel\": \"homelab-runtime\",\n380- \"command_id\": command_id,\n381- \"status\": status,\n382- \"rc\": int(rc),\n383- \"host\": host,\n384- \"mode\": mode,\n385- \"component\": component,\n386- \"started_at_utc\": started,\n387- \"finished_at_utc\": finished,\n388- \"reference_register_checked\": True,\n389- \"reference_sha256\": reference_sha,\n390- \"error_register_checked\": True,\n391- \"error_register_sha256\": error_sha,\n392- \"command_sha256\": command_sha,\n393- \"duplicate_failed_command_blocked\": repeat_blocked == \"true\",\n394: \"block_reason\": block_reason or None,\n395: \"execution_started\": run_started == \"true\",\n396: \"changes_made\": changes_made == \"true\",\n397- \"sanitized\": True,\n398- \"secrets_included\": False,\n399- \"private_addresses_included\": False,\n400- \"raw_evidence_retained_locally\": True,\n401- \"raw_evidence_sha256\": raw_sha,\n402- \"sanitized_output_sha256\": sanitized_sha,\n403- \"output_truncated_in_json\": output_truncated,\n404- \"full_sanitized_output_url\": (\n405- \"https://git.gram1.ru/.well-known/\"\n406- \"homelab-runtime/latest.txt\"\n407- ),\n408- \"output\": output_preview,\n409-}\n410-\n411-Path(json_path).write_text(\n412- json.dumps(\n413- document,\n414- ensure_ascii=False,\n415- indent=2,\n416- )\n417- + \"\\n\",\n418- encoding=\"utf-8\",\n419-)\n420-PY\n421-\n422-{\n423- echo 'CHAT_OUTPUT_BEGIN'\n424- echo \"COMMAND_ID=$COMMAND_ID\"\n425- echo \"STATUS=$STATUS\"\n426- echo \"RC=$RC\"\n427- echo \"HOST=$HOST_SHORT\"\n428- echo \"MODE=$MODE\"\n429- echo \"COMPONENT=$COMPONENT\"\n430- echo 'REFERENCE_REGISTER_CHECK=OK'\n431- echo \"REFERENCE_SHA256=$REFERENCE_SHA256\"\n432- echo 'ERROR_REGISTER_CHECK=OK'\n433- echo \"ERROR_REGISTER_SHA256=$ERROR_REGISTER_SHA256\"\n434- echo \"COMMAND_SHA256=$COMMAND_SHA256\"\n435- echo \"DUPLICATE_FAILED_COMMAND_BLOCKED=$REPEAT_BLOCKED\"\n436: echo \"EXECUTION_STARTED=$RUN_STARTED\"\n437: echo \"CHANGES_MADE=$CHANGES_MADE\"\n438- echo 'SANITIZED=yes'\n439- echo 'SECRETS_INCLUDED=no'\n440- echo 'PRIVATE_ADDRESSES_INCLUDED=no'\n441- echo \"RAW_EVIDENCE_SHA256=$RAW_SHA256\"\n442- echo \"SANITIZED_OUTPUT_SHA256=$SANITIZED_SHA256\"\n443- echo 'OUTPUT_BEGIN'\n444- cat \"$SANITIZED_FILE\"\n445- echo\n446- echo 'OUTPUT_END'\n447- echo 'CHAT_OUTPUT_END'\n448-} >\"$TXT_FILE\"\n449-\n450-chmod 0600 \\\n451- \"$RAW_FILE\" \\\n452- \"$SANITIZED_FILE\" \\\n453- \"$JSON_FILE\" \\\n454- \"$TXT_FILE\"\n455-\n456-TARGET=debian@[PRIVATE_IP]\n457-REMOTE_PREFIX=\"/tmp/homelab-runtime-${COMMAND_ID}-$$\"\n458-\n459-SSH_OPTS=(\n460- -o BatchMode=yes\n461- -o ConnectTimeout=10\n462- -o ConnectionAttempts=1\n463- -o StrictHostKeyChecking=yes\n464- -o UserKnownHostsFile=[SENSITIVE_PATH]\n465-)\n466-\n467-scp \\\n468- -q \\\n469- \"${SSH_OPTS[@]}\" \\\n470- \"$JSON_FILE\" \\\n471- \"${TARGET}:${REMOTE_PREFIX}.json\"\n472-\n473-scp \\\n474- -q \\\n475- \"${SSH_OPTS[@]}\" \\\n476- \"$TXT_FILE\" \\\n477- \"${TARGET}:${REMOTE_PREFIX}.txt\"\n=== MODE_REFERENCES ===\n11: read-only\n12: verify\n13: change\n14: transport-test\n51: read-only|verify|change|transport-test)\n150: change)\n357: changes_made,\n396: \"changes_made\": changes_made == \"true\",\nCLUSTER_REFERENCE_MODE_SEMANTICS=COMPLETE\n"
}