2026-03-28 19:18:32 -07:00
#!/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"
2026-04-12 06:12:20 -07:00
elif .category = = "rpc_core" or .category = = "rpc_public" or .category = = "rpc_private" or .category = = "rpc_named" or .category = = "rpc_thirdweb" or .category = = "rpc_thirdweb_specialized" or .category = = "rpc_alltra_hybx" then "Besu RPC (\(.category))"
2026-03-28 19:18:32 -07:00
elif .category = = "dlt" and ( .hostname | test( "fabric" ) ) then "Fabric"
elif .category = = "dlt" and ( .hostname | test( "indy" ) ) then "Indy"
elif .category = = "firefly" then "FireFly"
2026-04-12 06:12:20 -07:00
elif .category = = "identity_agent" then "Aries / AnonCreds"
elif .category = = "benchmark" then "Caliper"
2026-03-28 19:18:32 -07:00
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"
2026-04-12 06:12:20 -07:00
elif .category = = "dlt" or .category = = "firefly" or .category = = "identity_agent" then "identity / workflow DLT"
2026-03-28 19:18:32 -07:00
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
2026-03-28 23:21:51 -07:00
| [ ( .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]
2026-03-28 19:18:32 -07:00
| @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 6– 7) 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) .
2026-04-12 06:12:20 -07:00
## Canonical Chain 138 RPC Profiles
Verified live on 2026-04-09. Treat these profiles as the operating policy for the Besu RPC fleet:
- **Core / Admin:** \` 2101\` , \` 2102\` , \` 2103\` — may expose \` ADMIN\` ; used for operator/admin workflows.
- **Public:** \` 2201\` — \` ETH\` , \` NET\` , \` WEB3\` only; no \` ADMIN\` , \` DEBUG\` , or \` TRACE\` .
- **Permissioned / Private:** \` 2301\` , \` 2303\` , \` 2304\` , \` 2305\` , \` 2306\` , \` 2307\` , \` 2308\` , \` 2400\` , \` 2420\` , \` 2430\` , \` 2440\` , \` 2460\` , \` 2470\` , \` 2480\` — no \` ADMIN\` .
- **Thirdweb specialized RPC:** \` 2401\` , \` 2402\` , \` 2403\` — no \` ADMIN\` ; HTTP exposes \` ETH\` , \` NET\` , \` WEB3\` , \` DEBUG\` , \` TRACE\` ; WS exposes \` ETH\` , \` NET\` , \` WEB3\` .
2026-03-28 19:18:32 -07:00
## 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. |
2026-03-28 23:21:51 -07:00
| **Runtime state** | Current disposition from the planning template, e.g. active, placeholder CT only, or retired standby. |
2026-03-28 19:18:32 -07:00
| **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.
2026-03-28 23:21:51 -07:00
| VMID | Hostname | IPv4 | IP note | Node type | Runtime state | Entity owner | Region | Preferred host | Validator / signing | Security tier |
| ------| ----------| ------| ---------| -----------| ---------------| --------------| --------| ----------------| ---------------------| ---------------|
2026-03-28 19:18:32 -07:00
MID
2026-03-28 23:21:51 -07:00
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 | "
2026-03-28 19:18:32 -07:00
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.
2026-03-28 23:21:51 -07:00
| 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 |
2026-03-28 19:18:32 -07:00
## 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 "