#!/usr/bin/env bash # Regenerate docs/02-architecture/DBIS_NODE_ROLE_MATRIX.md body tables from # config/proxmox-operational-template.json (run from repo root). set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" JSON="$ROOT/config/proxmox-operational-template.json" OUT="$ROOT/docs/02-architecture/DBIS_NODE_ROLE_MATRIX.md" if ! command -v jq &>/dev/null; then echo "jq required" >&2 exit 1 fi TMP="$(mktemp)" trap 'rm -f "$TMP"' EXIT jq -r ' def vstatus: if .category == "besu_validator" then "QBFT signer" elif .category == "besu_sentry" then "Sentry (no signer)" elif (.category | test("^rpc")) then "RPC only" else "N/A" end; def ntype: if .category == "besu_validator" then "Besu validator" elif .category == "besu_sentry" then "Besu sentry" elif .category == "rpc_core" or .category == "rpc_public" or .category == "rpc_private" or .category == "rpc_named" or .category == "rpc_thirdweb" or .category == "rpc_alltra_hybx" then "Besu RPC (\(.category))" elif .category == "dlt" and (.hostname | test("fabric")) then "Fabric" elif .category == "dlt" and (.hostname | test("indy")) then "Indy" elif .category == "firefly" then "FireFly" elif .category == "explorer" then "Blockscout" elif .category == "npmplus" then "NPMplus ingress" elif .category == "infra" then "Infra LXC" elif .category == "monitoring" and (.hostname | test("cacti")) then "Cacti" elif .category == "monitoring" then "Monitoring" elif .category == "oracle" then "Oracle publisher" elif .category == "ccip" then "CCIP monitor" elif .category == "tunnel" then "Cloudflare tunnel" elif .category == "ml" then "ML node" elif .category == "vault" then "HashiCorp Vault" elif .category == "order" then "The Order service" elif .category == "sankofa_phoenix" then "Sankofa / Phoenix" elif .category == "mim4u" then "MIM4U" elif .category == "dbis" then "DBIS stack" elif .category == "mifos" then "Mifos" elif .category == "dapp" then "DApp" elif .category == "dev" then "Dev" elif .category == "ai_infra" then "AI infra" elif .category == "defi" then "DeFi" elif .category == "general" then "General CT" elif .category == "legacy_proxy" then "Legacy NPM" else .category end; def stier: if .category == "besu_validator" or .category == "besu_sentry" then "validator-tier" elif (.category | test("^rpc")) then "DMZ / RPC exposure" elif .category == "npmplus" or .category == "tunnel" then "edge ingress" elif .category == "dlt" or .category == "firefly" then "identity / workflow DLT" elif .category == "vault" or .category == "infra" then "management / secrets" elif .category == "order" or .category == "sankofa_phoenix" or .category == "dbis" then "application" else "standard internal" end; ([.services[] | select(.ipv4 != null) | .ipv4] | group_by(.) | map(select(length > 1) | .[0])) as $dup_ips | .services[] | (.ipv4) as $ip | [(.vmid // "—"), .hostname, ($ip // "—"), (if ($ip != null and ($dup_ips | index($ip))) then "shared / non-concurrent mapping — verify live owner" else "unique in template" end), ntype, (.runtime_state // "unspecified"), "TBD", "TBD", (.preferred_node // "—"), vstatus, stier] | @tsv ' "$JSON" | sort -t$'\t' -k1,1n > "$TMP" UPDATED="$(date -u +%Y-%m-%d)" { cat < "$OUT" echo "Wrote $OUT"