{
  "schema_version": 1,
  "channel": "homelab-runtime",
  "command_id": "GRAM1-SITE-AVAX-LINK-V17-DEBIAN-SUDO-EXACT-SOURCE-CAPTURE-20260731T211900Z",
  "status": "OK",
  "rc": 0,
  "host": "pve01",
  "mode": "verify",
  "component": "gram1-site-avax-link-v17-debian-sudo-exact-source-capture",
  "started_at_utc": "2026-07-31T21:20:57Z",
  "finished_at_utc": "2026-07-31T21:20:57Z",
  "reference_register_checked": true,
  "reference_sha256": "5763f2f8edc75fcf6f3951f8c95896d1cc112ceccb6cf5b64a383f540a4deb8e",
  "error_register_checked": true,
  "error_register_sha256": "24934a2c7fa5c26f6e828583c4aefac7f143b40c0171736ed7571e617d55ab83",
  "command_sha256": "404219cce138c7f6c61eae8e1bab74591903744c97981970ff999945e673d6c5",
  "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": "59c2fd75df79dad54983661a95529fb1a8e10ed812c3777ca5ba2439d1f19c3d",
  "sanitized_output_sha256": "59c2fd75df79dad54983661a95529fb1a8e10ed812c3777ca5ba2439d1f19c3d",
  "output_truncated_in_json": false,
  "full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt",
  "output": "HOMELAB_RESULT_CONTRACT={\"changes_made\":false,\"command_id\":\"GRAM1-SITE-AVAX-LINK-V17-DEBIAN-SUDO-EXACT-SOURCE-CAPTURE-20260731T211900Z\",\"mutation_outcome\":\"NO_MUTATION\",\"rollback_restored\":null,\"rollback_started\":false,\"status\":\"OK\",\"version\":1}\n{\"changes_made\":false,\"command_id\":\"GRAM1-SITE-AVAX-LINK-V17-DEBIAN-SUDO-EXACT-SOURCE-CAPTURE-20260731T211900Z\",\"control_plane_error\":null,\"gitea_changed\":false,\"known_host_reference_count\":1,\"mutation_outcome\":\"NO_MUTATION\",\"next_decision\":\"BUILD_TRANSACTIONAL_AVAX_LINK_CHANGE\",\"output_json_bytes_before_size_field\":37042,\"previous_capsule_sha256\":\"2a7e1500556cfc02dd1eeb945a298b96396255ae98be26fa67ff7b75fa25b0e5\",\"previous_command_id\":\"GRAM1-SITE-AVAX-LINK-V16-DEBIAN-SSH-EXACT-SOURCE-CAPTURE-20260731T211300Z\",\"production_site_changed\":false,\"proven_v16_failure\":\"DEBIAN_SSH_IDENTITY_VERIFIED_BUT_SOURCE_CAPTURE_ABORTED_ON_PERMISSION_DENIED_FOR_OPT_STACKS_CRYPTO_PORTFOLIO_APP_PY\",\"rc\":0,\"remote_execution\":{\"classification\":\"OK\",\"duration_seconds\":0.158,\"method\":\"ALIAS_PINNED_AS_DEBIAN\",\"rc\":0,\"report\":{\"core_candidates\":[{\"exists\":true,\"relative_path\":\"app.py\"},{\"exists\":true,\"relative_path\":\"worker.py\"},{\"exists\":true,\"relative_path\":\"templates/index.html\"},{\"exists\":true,\"relative_path\":\"compose.yaml\"},{\"exists\":false,\"relative_path\":\"compose.yml\"},{\"exists\":false,\"relative_path\":\"docker-compose.yml\"},{\"exists\":false,\"relative_path\":\"docker-compose.yaml\"},{\"exists\":true,\"relative_path\":\"Dockerfile\"},{\"exists\":true,\"relative_path\":\"requirements.txt\"},{\"exists\":false,\"relative_path\":\"pyproject.toml\"},{\"exists\":false,\"relative_path\":\"package.json\"}],\"deadline_hit\":false,\"deadline_seconds\":7.0,\"discovery\":[{\"bytes\":17955,\"hits\":[{\"line\":9,\"text\":\"DB = DATA / \\\"portfolio.db\\\"\"},{\"line\":13,\"text\":\"COINS = {\\\"hedera-hashgraph\\\": \\\"HBAR\\\", \\\"polygon-ecosystem-token\\\": \\\"POL\\\"}\"},{\"line\":89,\"text\":\"    return {\\\"status\\\":\\\"OK\\\",\\\"type\\\":\\\"crypto-portfolio\\\",\\\"market_age_seconds\\\":age}\"},{\"line\":111,\"text\":\"        with httpx.Client(timeout=6, headers={\\\"User-Agent\\\":\\\"Gram-Crypto-Portfolio/1.0\\\"}) as client:\"},{\"line\":112,\"text\":\"            response = client.get(\\\"https://api.coingecko.com/api/v3/coins/markets\\\", params={\\\"vs_currency\\\":\\\"usd\\\",\\\"ids\\\":coin_id,\\\"sparkline\\\":\\\"false\\\"})\"},{\"line\":128,\"text\":\"        symbols = {\\\"bitcoin\\\":\\\"₿\\\",\\\"ethereum\\\":\\\"Ξ\\\",\\\"solana\\\":\\\"S\\\",\\\"binancecoin\\\":\\\"BNB\\\",\\\"ripple\\\":\\\"XRP\\\",\\\"cardano\\\":\\\"ADA\\\",\\\"hedera-hashgraph\\\":\\\"HBAR\\\",\\\"hedera\\\":\\\"HBAR\\\",\\\"chainlink\\\":\\\"LINK\\\",\\\"toncoin\\\":\\\"TON\\\",\\\"dogecoin\\\":\\\"Ð\\\"}\"},{\"line\":129,\"text\":\"        label = symbols.get(coin_id, coin_id[:3].upper())\"},{\"line\":138,\"text\":\"LIGHTWEIGHT_JS = DATA / \\\"lightweight-charts.standalone.production.js\\\"\"}],\"relative_path\":\"app.py\",\"sha256\":\"44df2b25183b7c5d87ff1516ec2d9cd1d169acde3031f7c2aa1fc4e0c7813cd2\"},{\"bytes\":1233,\"hits\":[{\"line\":4,\"text\":\"    container_name: crypto-portfolio\"},{\"line\":29,\"text\":\"    container_name: crypto-portfolio-worker\"}],\"relative_path\":\"compose.yaml\",\"sha256\":\"6d344e46b3de94ad86131a914df2ff3ff25e9d82f7ce0557cbffa468b8cdc1b8\"},{\"bytes\":29469,\"hits\":[{\"line\":3,\"text\":\"<style>:root{--bg:#071018;--p:#0f1d29;--p2:#0a1620;--l:#213644;--t:#f3f7fb;--m:#8fa5b6;--g:#63e6be;--r:#ff6b81;--b:#69a7ff}*{box-sizing:border-box}body{margin:0;background:radial-gradient(circle at 85% 0,#17395a55,transparent 32%),var(--bg);color:var(--t);font:14px system-ui}.app{max-width:1500px;margin:auto;padding:24px}.top{display:flex;justify-content:space-between;align-items:center;margin-bottom:18px}.top-actions{display:flex;align-items:center;gap:10px}.currency-switch{display:flex;gap:4px;padding:4px;border:1px solid var(--l);border-radius:12px;background:#091722}.currency-btn{border:0;\"},{\"line\":6,\"text\":\"<section id=\\\"coins\\\" class=\\\"coins\\\"></section><section class=\\\"layout\\\"><div class=\\\"panel\\\"><div class=\\\"title\\\"><div><h2 id=\\\"chartTitle\\\">График цены</h2><span class=\\\"muted\\\">7 дней</span></div><span id=\\\"marketStatus\\\" class=\\\"status\\\">Загрузка</span></div><svg id=\\\"chart\\\" class=\\\"chart\\\" viewBox=\\\"0 0 900 270\\\" preserveAspectRatio=\\\"none\\\"></svg></div><div class=\\\"panel sharp-moves-panel\\\"><div class=\\\"title\\\"><h2>Резкие движения</h2></div><div id=\\\"moves\\\" class=\\\"moves\\\"></div></div></section>\"},{\"line\":9,\"text\":\"<script>let state=null;let selected=\\\"hedera-hashgraph\\\";let currency=localStorage.getItem(\\\"portfolio_currency\\\")===\\\"RUB\\\"?\\\"RUB\\\":\\\"USD\\\";const fx=()=>Number(state&&state.market&&state.market.usd_rub||0);const cv=n=>Number(n||0)*(currency===\\\"RUB\\\"?fx():1);const money=(n,d=2)=>new Intl.NumberFormat(currency===\\\"RUB\\\"?\\\"ru-RU\\\":\\\"en-US\\\",{style:\\\"currency\\\",currency:currency,minimumFractionDigits:d,maximumFractionDigits:d}).format(cv(n));const compactMoney=n=>(currency===\\\"RUB\\\"?\\\"₽\\\":\\\"$\\\")+new Intl.NumberFormat(currency===\\\"RUB\\\"?\\\"ru-RU\\\":\\\"en-US\\\",{notation:\\\"compact\\\",maximumFractionDigits:2}).format(cv(n));const inputP\"},{\"line\":132,\"text\":\"    const symbol=(data.coins&&data.coins[alert.coin_id])||alert.coin_id;\"},{\"line\":134,\"text\":\"    if([\\\"pump\\\",\\\"dump\\\"].includes(alert.kind))return symbol+\\\": \\\"+kind+\\\" \\\"+Number(alert.threshold).toLocaleString(\\\"ru-RU\\\",{maximumFractionDigits:12})+\\\"%\\\";\"},{\"line\":135,\"text\":\"    return symbol+\\\": \\\"+kind+\\\" \\\"+alertMoney(data,alert.threshold);\"},{\"line\":217,\"text\":\"<style id=\\\"TRADINGVIEW_THREE_CHARTS_STYLE_V1\\\">#chart{display:none!important}#tvCharts{display:grid;grid-template-columns:1fr;gap:18px;margin-top:12px}.tv-card{min-height:470px;border:1px solid var(--l);border-radius:16px;overflow:hidden;background:#081823}.tv-card-head{padding:12px 14px 0;font-weight:800}.tv-widget-slot{height:430px;width:100%}@media(max-width:750px){.tv-widget-slot{height:370px}}</style>\"},{\"line\":218,\"text\":\"<script src=\\\"/vendor/lightweight-charts.js\\\"></script>\"}],\"relative_path\":\"templates/index.html\",\"sha256\":\"e497a36d8549654c6d451360a11a2ad714e19c23e6d384330a5436f7d32267cb\"},{\"bytes\":10256,\"hits\":[{\"line\":7,\"text\":\"DB = DATA / \\\"portfolio.db\\\"\"},{\"line\":11,\"text\":\"COINS = {\\\"hedera-hashgraph\\\": \\\"HBAR\\\", \\\"polygon-ecosystem-token\\\": \\\"POL\\\"}\"},{\"line\":43,\"text\":\"    with httpx.Client(timeout=25, headers={\\\"User-Agent\\\":\\\"Gram-Crypto-Portfolio/1.0\\\"}) as client:\"},{\"line\":44,\"text\":\"        r = client.get(\\\"https://api.coingecko.com/api/v3/coins/markets\\\", params=params)\"},{\"line\":57,\"text\":\"        with httpx.Client(timeout=15, headers={\\\"User-Agent\\\":\\\"Gram-Crypto-Portfolio/1.0\\\"}) as fx_client:\"},{\"line\":58,\"text\":\"            fx_data = fx_client.get(\\\"https://api.coingecko.com/api/v3/simple/price\\\", params={\\\"ids\\\":\\\"bitcoin\\\",\\\"vs_currencies\\\":\\\"usd,rub\\\"}).json()[\\\"bitcoin\\\"]\"},{\"line\":72,\"text\":\"        result[\\\"coins\\\"][cid] = {\\\"symbol\\\":COINS[cid],\\\"name\\\":x.get(\\\"name\\\"),\\\"price\\\":float(x.get(\\\"current_price\\\") or 0),\\\"market_cap\\\":float(x.get(\\\"market_cap\\\") or 0),\\\"rank\\\":x.get(\\\"market_cap_rank\\\"),\\\"volume\\\":float(x.get(\\\"total_volume\\\") or 0),\\\"high_24h\\\":x.get(\\\"high_24h\\\"),\\\"low_24h\\\":x.get(\\\"low_24h\\\"),\\\"change_1h\\\":x.get(\\\"price_change_percentage_1h_in_currency\\\"),\\\"change_24h\\\":x.get(\\\"price_change_percentage_24h_in_currency\\\"),\\\"change_7d\\\":x.get(\\\"price_change_percentage_7d_in_currency\\\"),\\\"sparkline_7d\\\":((x.get(\\\"sparkline_in_7d\\\") or {}).get(\\\"price\\\") or []),\\\"last_updated\\\":x.get(\\\"last_updated\\\")}\"},{\"line\":107,\"text\":\"def portfolio_text(c, coin_id, price):\"}],\"relative_path\":\"worker.py\",\"sha256\":\"174a14b86014535980d200a76d0057110c7af102c66f16c2e21fc3e74bb2e49e\"}],\"discovery_limit_hit\":false,\"duration_seconds\":0.023,\"files_scanned\":30,\"hostname\":\"core-apps\",\"root\":\"/opt/stacks/crypto-portfolio\",\"root_exists\":true,\"schema\":2,\"source_bundle\":{\"b64\":\"[encoded data, 25836 characters]\",\"compressed_bytes\":19376,\"compressed_sha256\":\"81c079a94543bb046ab3c2fbbd9b0aa0aa79ed66c1f7b651a7b2a633c5ec93be\",\"encoding\":\"gzip+base64\",\"file_count\":6,\"uncompressed_bytes\":63818,\"uncompressed_sha256\":\"249586886d7a9205716c6d205b3c9e3967151aada023423a77b844ff03c89c7d\"},\"source_files\":[{\"bytes\":17955,\"content_in_bundle\":true,\"line_count\":395,\"redactions\":[{\"kind\":\"sensitive_assignment\",\"line\":12}],\"relative_path\":\"app.py\",\"sanitized_sha256\":\"f17e00535770261d74098de0e9bd6343e0352a8f69444d03d0c319634ed2cc2d\",\"sha256\":\"44df2b25183b7c5d87ff1516ec2d9cd1d169acde3031f7c2aa1fc4e0c7813cd2\"},{\"bytes\":10256,\"content_in_bundle\":true,\"line_count\":203,\"redactions\":[{\"kind\":\"sensitive_assignment\",\"line\":89}],\"relative_path\":\"worker.py\",\"sanitized_sha256\":\"590fb3e39460675b60630233687071f0876120cc62435ae16ca595def7a021fa\",\"sha256\":\"174a14b86014535980d200a76d0057110c7af102c66f16c2e21fc3e74bb2e49e\"},{\"bytes\":29469,\"content_in_bundle\":true,\"line_count\":276,\"redactions\":[],\"relative_path\":\"templates/index.html\",\"sanitized_sha256\":\"e497a36d8549654c6d451360a11a2ad714e19c23e6d384330a5436f7d32267cb\",\"sha256\":\"e497a36d8549654c6d451360a11a2ad714e19c23e6d384330a5436f7d32267cb\"},{\"bytes\":1233,\"content_in_bundle\":true,\"line_count\":53,\"redactions\":[{\"kind\":\"private_address\",\"line\":7},{\"kind\":\"sensitive_assignment\",\"line\":11},{\"kind\":\"sensitive_assignment\",\"line\":12}],\"relative_path\":\"compose.yaml\",\"sanitized_sha256\":\"00d07541be95f2c01098ddb9505a24d0549f017d441a6718cef49262e9d1dd01\",\"sha256\":\"6d344e46b3de94ad86131a914df2ff3ff25e9d82f7ce0557cbffa468b8cdc1b8\"},{\"bytes\":465,\"content_in_bundle\":true,\"line_count\":11,\"redactions\":[],\"relative_path\":\"Dockerfile\",\"sanitized_sha256\":\"a5d546ddb9b4fac44cc00a43c18a18a8cdb246afea4dfc945089759d0dec0fcb\",\"sha256\":\"a5d546ddb9b4fac44cc00a43c18a18a8cdb246afea4dfc945089759d0dec0fcb\"},{\"bytes\":123,\"content_in_bundle\":true,\"line_count\":6,\"redactions\":[],\"relative_path\":\"requirements.txt\",\"sanitized_sha256\":\"5dec3868a6a71a7dc8810b57acae9de25b99cae6978cd1750f4b0c01b27055a2\",\"sha256\":\"5dec3868a6a71a7dc8810b57acae9de25b99cae6978cd1750f4b0c01b27055a2\"}],\"source_scope_complete\":true},\"stderr\":\"Authenticated to <PRIVATE_ADDRESS> ([<PRIVATE_ADDRESS>]:22) using \\\"publickey\\\". Transferred: sent 14476, received 38648 bytes, in 0.1 seconds Bytes per second: sent 207030.7, received 552730.1\"},\"remote_user_override\":\"debian\",\"rollback_restored\":null,\"rollback_started\":false,\"schema\":1,\"selected_method\":\"ALIAS_PINNED_AS_DEBIAN\",\"source_bundle_verified\":{\"compressed_sha256\":\"81c079a94543bb046ab3c2fbbd9b0aa0aa79ed66c1f7b651a7b2a633c5ec93be\",\"file_count\":6,\"uncompressed_sha256\":\"249586886d7a9205716c6d205b3c9e3967151aada023423a77b844ff03c89c7d\",\"verified\":true},\"ssh_config_summary\":{\"configured_user_is_root\":true,\"hostname_is_pinned_address\":false,\"identityfile_count\":6,\"port\":22,\"proxycommand_present\":false,\"proxyjump_present\":false,\"remote_user_override\":\"debian\",\"resolved\":true,\"user_present\":true},\"ssh_method_probes\":[{\"classification\":\"OK\",\"duration_seconds\":0.108,\"hostname\":\"core-apps\",\"identity_matches\":true,\"name\":\"ALIAS_PINNED_AS_DEBIAN\",\"rc\":0,\"remote_user\":\"debian\",\"resolved_identity_count\":null,\"stderr\":\"Authenticated to <PRIVATE_ADDRESS> ([<PRIVATE_ADDRESS>]:22) using \\\"publickey\\\". Transferred: sent 4312, received 4120 bytes, in 0.0 seconds Bytes per second: sent 172086.7, received 164424.2\"},{\"classification\":\"OK\",\"duration_seconds\":0.112,\"hostname\":\"core-apps\",\"identity_matches\":true,\"name\":\"DIRECT_PINNED_AS_DEBIAN_NO_PROXY\",\"rc\":0,\"remote_user\":\"debian\",\"resolved_identity_count\":2,\"stderr\":\"Authenticated to <PRIVATE_ADDRESS> ([<PRIVATE_ADDRESS>]:22) using \\\"publickey\\\". Transferred: sent 4312, received 4120 bytes, in 0.0 seconds Bytes per second: sent 166205.3, received 158804.7\"}],\"status\":\"OK\",\"tcp_probe\":{\"connected\":true,\"duration_seconds\":0.001,\"error\":null}}\n"
}
