Files
proxmox/scripts/docs/generate-dbis-node-role-matrix-md.sh

150 lines
8.0 KiB
Bash
Raw Normal View History

#!/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 <<EOF
# DBIS Node Role Matrix
**Last updated:** ${UPDATED} (UTC) — regenerate machine-derived rows: \`bash scripts/docs/generate-dbis-node-role-matrix-md.sh\`
**Status:** Active — infrastructure constitution for DBIS Chain 138 and colocated workloads.
## Purpose
This matrix assigns **node type**, **preferred host placement**, **validator/signing role** (for Besu), and **security tier** per workload. It implements the entity-placement model in [dbis_chain_138_technical_master_plan.md](../../dbis_chain_138_technical_master_plan.md) (Sections 67) in a form operators can maintain.
**Canonical pairs (keep in sync):**
- Human detail and status: [ALL_VMIDS_ENDPOINTS.md](../04-configuration/ALL_VMIDS_ENDPOINTS.md)
- Machine-readable services: [config/proxmox-operational-template.json](../../config/proxmox-operational-template.json)
When you change VMID, IP, hostname, or placement, update **ALL_VMIDS** and **operational-template.json** first, then regenerate the table below with this script (or edit the static sections manually).
## Columns
| Column | Meaning |
|--------|---------|
| **Entity owner** | DBIS Core, Central Bank, IFI, Regional Operator, etc. — use **TBD** until governance assigns. |
| **Region** | Geographic or site label — **TBD** until multi-site is formalized. |
| **IP note** | Flags duplicate IPv4 entries in the planning template. A duplicate means **shared or historical mapping**, not concurrent ownership — verify live owner in ALL_VMIDS or on-cluster. |
| **Runtime state** | Current disposition from the planning template, e.g. active, placeholder CT only, or retired standby. |
| **Preferred host** | Preferred Proxmox node (\`r630-01\`, \`r630-02\`, \`ml110\`, \`any\`). This is a planning target, not an assertion of current placement. |
| **Validator / signing** | For Chain 138 Besu: QBFT signer, sentry (no signer), RPC-only, or N/A. |
| **Security tier** | High-level zone: validator-tier, DMZ/RPC, edge ingress, identity/DLT, application, etc. |
## Proxmox hypervisor nodes
| Hostname | MGMT IP | Cluster | Role (summary) |
|----------|---------|---------|------------------|
EOF
jq -r '.proxmox_nodes[] | "| \(.hostname) | \(.mgmt_ipv4) | \(.cluster_name // "h — verify") | \(.role) |"' "$JSON"
cat <<'MID'
## Workloads (from operational template)
Machine-derived rows below come from `services[]` in `config/proxmox-operational-template.json`. Duplicate IPv4 notes are warnings that the planning template still contains alternative or legacy ownership for the same address; they must not be read as concurrent live allocations.
| VMID | Hostname | IPv4 | IP note | Node type | Runtime state | Entity owner | Region | Preferred host | Validator / signing | Security tier |
|------|----------|------|---------|-----------|---------------|--------------|--------|----------------|---------------------|---------------|
MID
while IFS=$'\t' read -r vmid host ip ipnote ntype rstate ent reg hw vst stier; do
echo "| $vmid | $host | $ip | $ipnote | $ntype | $rstate | $ent | $reg | $hw | $vst | $stier |"
done < "$TMP"
cat <<'FOOT'
## Supplementary rows (not in template JSON)
These appear in [ALL_VMIDS_ENDPOINTS.md](../04-configuration/ALL_VMIDS_ENDPOINTS.md) but are not modeled as `services[]` entries in `proxmox-operational-template.json`. They are **manual supplements**, not generator-backed source of truth.
| VMID | Hostname | IPv4 | IP note | Node type | Runtime state | Entity owner | Region | Preferred host | Validator / signing | Security tier |
|------|----------|------|---------|-----------|---------------|--------------|--------|----------------|---------------------|---------------|
| 106 | redis-rpc-translator | 192.168.11.110 | manual supplement | RPC translator (Redis) | manual supplement | TBD | TBD | r630-01 (per ALL_VMIDS) | N/A | DMZ / RPC exposure |
| 107 | web3signer-rpc-translator | 192.168.11.111 | manual supplement | RPC translator (Web3Signer) | manual supplement | TBD | TBD | r630-01 | N/A | DMZ / RPC exposure |
| 108 | vault-rpc-translator | 192.168.11.112 | manual supplement | RPC translator (Vault) | manual supplement | TBD | TBD | r630-01 | N/A | management / secrets |
## Host-level services (no VMID)
| Name | Location | Node type | Notes |
|------|----------|-----------|-------|
| CCIP relay | r630-01 host `/opt/smom-dbis-138/services/relay` | Cross-chain relay | Uses RPC (e.g. VMID 2201); see [NETWORK_CONFIGURATION_MASTER.md](../11-references/NETWORK_CONFIGURATION_MASTER.md), [docs/07-ccip/](../07-ccip/). |
## Related
- [dbis_chain_138_technical_master_plan.md](../../dbis_chain_138_technical_master_plan.md)
- [CHAIN138_CANONICAL_NETWORK_ROLES_VALIDATORS_SENTRY_AND_RPC.md](CHAIN138_CANONICAL_NETWORK_ROLES_VALIDATORS_SENTRY_AND_RPC.md)
- [VMID_ALLOCATION_FINAL.md](VMID_ALLOCATION_FINAL.md)
FOOT
} > "$OUT"
echo "Wrote $OUT"