2026-02-12 15:46:57 -08:00
#!/usr/bin/env bash
# Validate required config files and optional env vars before deployment/scripts
# Recommendation: docs/10-best-practices/IMPLEMENTATION_CHECKLIST.md (Configuration validation)
2026-02-21 15:46:06 -08:00
# Usage: ./scripts/validation/validate-config-files.sh [--dry-run]
# --dry-run Print what would be validated and exit 0 (no file checks).
2026-02-12 15:46:57 -08:00
set -euo pipefail
SCRIPT_DIR = " $( cd " $( dirname " ${ BASH_SOURCE [0] } " ) " && pwd ) "
PROJECT_ROOT = " $( cd " $SCRIPT_DIR /../.. " && pwd ) "
2026-02-21 15:46:06 -08:00
DRY_RUN = false
for a in " $@ " ; do [ [ " $a " = = "--dry-run" ] ] && DRY_RUN = true && break; done
2026-02-12 15:46:57 -08:00
log_info( ) { echo " [INFO] $1 " ; }
log_ok( ) { echo " [OK] $1 " ; }
log_warn( ) { echo " [WARN] $1 " ; }
log_err( ) { echo " [ERROR] $1 " ; }
ERRORS = 0
# Required config paths (adjust per project)
REQUIRED_FILES = " ${ VALIDATE_REQUIRED_FILES :- } "
# Example: REQUIRED_FILES="/path/to/config.toml /path/to/.env"
2026-03-02 11:37:34 -08:00
# Optional env vars to warn if missing (default empty = no warnings; set VALIDATE_OPTIONAL_ENV for Proxmox API checks)
OPTIONAL_ENV = " ${ VALIDATE_OPTIONAL_ENV :- } "
2026-02-12 15:46:57 -08:00
check_file( ) {
local f = " $1 "
if [ [ -f " $f " ] ] ; then
log_ok " Found: $f "
return 0
else
log_err " Missing required file: $f "
ERRORS = $(( ERRORS + 1 ))
return 1
fi
}
check_env( ) {
local name = " $1 "
if [ [ -z " ${ !name :- } " ] ] ; then
log_warn " Optional env not set: $name "
return 1
else
log_ok " Env set: $name "
return 0
fi
}
2026-02-21 15:46:06 -08:00
if $DRY_RUN ; then
echo "=== Validation (--dry-run: would check) ==="
2026-03-31 22:52:53 -07:00
echo " REQUIRED_FILES: ${ REQUIRED_FILES :- <default : config/ip-addresses.conf, .env.example, token-mapping*.json, gru-transport-active.json, gru-iso4217-currency-manifest.json, gru-governance-supervision-profile.json> } "
2026-03-02 11:37:34 -08:00
echo " OPTIONAL_ENV: ${ OPTIONAL_ENV :- <empty; set VALIDATE_OPTIONAL_ENV for Proxmox API vars> } "
2026-04-01 11:28:41 -07:00
echo " config/xdc-zero: validate-xdc-zero-config.sh (when config/xdc-zero exists)"
2026-02-21 15:46:06 -08:00
exit 0
fi
2026-02-12 15:46:57 -08:00
if [ [ -n " $REQUIRED_FILES " ] ] ; then
for f in $REQUIRED_FILES ; do
check_file " $f "
done
else
# Default: check common locations
[ [ -d " $PROJECT_ROOT /config " ] ] && check_file " $PROJECT_ROOT /config/ip-addresses.conf " || true
chore: sync docs, config schemas, scripts, and meta task alignment
- Institutional / JVMTM / reserve-provenance / GRU transport + standards JSON
- Validation and verify scripts (Blockscout labels, x402, GRU preflight, P1 local path)
- Wormhole wiring in AGENTS, MCP_SETUP, MASTER_INDEX, 04-configuration README
- Meta docs, integration gaps, live verification log, architecture updates
- CI validate-config workflow updates
Operator/LAN items, submodule working trees, and public token-aggregation edge
routes remain follow-up (see TODOS_CONSOLIDATED P1).
Made-with: Cursor
2026-03-31 22:31:39 -07:00
[ [ -f " $PROJECT_ROOT /config/smart-contracts-master.json " ] ] && check_file " $PROJECT_ROOT /config/smart-contracts-master.json " || true
2026-02-12 15:46:57 -08:00
[ [ -f " $PROJECT_ROOT /.env.example " ] ] && log_ok ".env.example present (copy to .env and fill)" || true
2026-02-21 15:46:06 -08:00
# Token mapping (Chain 138 ↔ Mainnet): optional but validate structure if present
if [ [ -f " $PROJECT_ROOT /config/token-mapping.json " ] ] ; then
log_ok "Found: config/token-mapping.json"
if command -v jq & >/dev/null; then
if jq -e '.tokens | type == "array"' " $PROJECT_ROOT /config/token-mapping.json " & >/dev/null; then
log_ok "token-mapping.json: valid JSON with .tokens array"
else
log_err "token-mapping.json: invalid or missing .tokens array"
ERRORS = $(( ERRORS + 1 ))
fi
fi
2026-03-02 11:37:34 -08:00
elif [ [ -f " $PROJECT_ROOT /config/token-mapping-multichain.json " ] ] && command -v jq & >/dev/null && jq -e '.pairs | type == "array"' " $PROJECT_ROOT /config/token-mapping-multichain.json " & >/dev/null; then
log_ok "Token mapping: using config/token-mapping-multichain.json (relay fallback)"
2026-02-21 15:46:06 -08:00
else
log_warn "Optional config/token-mapping.json not found (relay uses fallback mapping)"
fi
if [ [ -f " $PROJECT_ROOT /config/token-mapping-multichain.json " ] ] ; then
log_ok "Found: config/token-mapping-multichain.json"
if command -v jq & >/dev/null; then
if jq -e '.pairs | type == "array"' " $PROJECT_ROOT /config/token-mapping-multichain.json " & >/dev/null; then
log_ok "token-mapping-multichain.json: valid JSON with .pairs array"
else
log_err "token-mapping-multichain.json: invalid or missing .pairs array"
ERRORS = $(( ERRORS + 1 ))
fi
fi
fi
chore: sync docs, config schemas, scripts, and meta task alignment
- Institutional / JVMTM / reserve-provenance / GRU transport + standards JSON
- Validation and verify scripts (Blockscout labels, x402, GRU preflight, P1 local path)
- Wormhole wiring in AGENTS, MCP_SETUP, MASTER_INDEX, 04-configuration README
- Meta docs, integration gaps, live verification log, architecture updates
- CI validate-config workflow updates
Operator/LAN items, submodule working trees, and public token-aggregation edge
routes remain follow-up (see TODOS_CONSOLIDATED P1).
Made-with: Cursor
2026-03-31 22:31:39 -07:00
if [ [ -f " $PROJECT_ROOT /config/gru-transport-active.json " ] ] ; then
log_ok "Found: config/gru-transport-active.json"
if command -v jq & >/dev/null; then
if jq -e '
( .system.name | type = = "string" )
and ( .system.shortName | type = = "string" )
and ( .enabledCanonicalTokens | type = = "array" )
and ( .enabledDestinationChains | type = = "array" )
and ( .approvedBridgePeers | type = = "array" )
and ( .transportPairs | type = = "array" )
and ( .publicPools | type = = "array" )
' " $PROJECT_ROOT /config/gru-transport-active.json " & >/dev/null; then
log_ok "gru-transport-active.json: top-level overlay structure is valid"
else
log_err "gru-transport-active.json: invalid top-level structure"
ERRORS = $(( ERRORS + 1 ))
fi
fi
if command -v node & >/dev/null; then
if PROJECT_ROOT = " $PROJECT_ROOT " node <<'NODE'
const fs = require( 'fs' ) ;
const path = require( 'path' ) ;
const projectRoot = process.env.PROJECT_ROOT;
function readJson( relativePath) {
return JSON.parse( fs.readFileSync( path.join( projectRoot, relativePath) , 'utf8' ) ) ;
}
function normalizeAddress( address) {
return typeof address = = = 'string' ? address.trim( ) .toLowerCase( ) : '' ;
}
function isNonZeroAddress( address) {
const normalized = normalizeAddress( address) ;
return /^0x[ a-f0-9] { 40} $/.test( normalized) && normalized != = '0x0000000000000000000000000000000000000000' ;
}
function refConfigured( ref) {
return !!ref && typeof ref = = = 'object' && (
( typeof ref.address = = = 'string' && ref.address.trim( ) != = '' ) ||
( typeof ref.env = = = 'string' && ref.env.trim( ) != = '' )
) ;
}
const active = readJson( 'config/gru-transport-active.json' ) ;
const multichain = readJson( 'config/token-mapping-multichain.json' ) ;
const deployment = readJson( 'cross-chain-pmm-lps/config/deployment-status.json' ) ;
const poolMatrix = readJson( 'cross-chain-pmm-lps/config/pool-matrix.json' ) ;
const currencyManifest = readJson( 'config/gru-iso4217-currency-manifest.json' ) ;
const errors = [ ] ;
const canonicalChainId = Number( active.system?.canonicalChainId ?? 138) ;
const enabledCanonicalTokens = Array.isArray( active.enabledCanonicalTokens) ? active.enabledCanonicalTokens : [ ] ;
const enabledCanonical = new Set( enabledCanonicalTokens.map( ( token) = > String( token.symbol) ) ) ;
const enabledChainsArray = Array.isArray( active.enabledDestinationChains) ? active.enabledDestinationChains : [ ] ;
const enabledChains = new Set( enabledChainsArray.map( ( chain) = > Number( chain.chainId) ) ) ;
const peersByKey = new Map( ( active.approvedBridgePeers || [ ] ) .map( ( peer) = > [ String( peer.key) , peer] ) ) ;
const reserveVerifiers = active.reserveVerifiers && typeof active.reserveVerifiers = = = 'object'
? active.reserveVerifiers
: { } ;
const transportPairsByKey = new Map( ( active.transportPairs || [ ] ) .map( ( pair) = > [ String( pair.key) , pair] ) ) ;
const publicPoolsByKey = new Map( ( active.publicPools || [ ] ) .map( ( pool) = > [ String( pool.key) , pool] ) ) ;
const manifestByCode = new Map( ( currencyManifest.currencies || [ ] ) .map( ( currency) = > [ String( currency.code) , currency] ) ) ;
function getMappingPair( fromChainId, toChainId) {
return ( multichain.pairs || [ ] ) .find(
( entry) = > Number( entry.fromChainId) = = = Number( fromChainId) && Number( entry.toChainId) = = = Number( toChainId)
) ;
}
function getMappingToken( fromChainId, toChainId, mappingKey) {
const pair = getMappingPair( fromChainId, toChainId) ;
if ( !pair) return null;
return ( pair.tokens || [ ] ) .find( ( token) = > token.key = = = mappingKey) || null;
}
function getExpectedPoolKey( chainId, mirroredSymbol) {
const chain = poolMatrix.chains?.[ String( chainId) ] ;
const hubStable = typeof chain?.hubStable = = = 'string' ? chain.hubStable.trim( ) : '' ;
if ( !hubStable) return null;
return ` ${ chainId } -${ mirroredSymbol } -${ hubStable } ` ;
}
for ( const chain of active.enabledDestinationChains || [ ] ) {
if ( !peersByKey.has( String( chain.peerKey || '' ) ) ) {
errors.push( ` enabledDestinationChains[ ${ chain .chainId } ] references missing peerKey ${ chain .peerKey } ` ) ;
}
}
for ( const token of enabledCanonicalTokens) {
const currency = manifestByCode.get( String( token.currencyCode || '' ) ) ;
if ( !currency) {
errors.push( ` enabledCanonicalTokens[ ${ token .symbol } ] references missing currencyCode ${ token .currencyCode } in gru-iso4217-currency-manifest.json` ) ;
continue ;
}
if ( currency.status?.deployed != = true ) {
errors.push( ` enabledCanonicalTokens[ ${ token .symbol } ] requires manifest currency ${ token .currencyCode } to be deployed` ) ;
}
if ( currency.status?.transportActive != = true ) {
errors.push( ` enabledCanonicalTokens[ ${ token .symbol } ] requires manifest currency ${ token .currencyCode } to mark transportActive = true ` ) ;
}
}
for ( const pair of active.transportPairs || [ ] ) {
const canonicalChainId = Number( pair.canonicalChainId ?? active.system?.canonicalChainId ?? 138) ;
const destinationChainId = Number( pair.destinationChainId) ;
const canonicalSymbol = String( pair.canonicalSymbol || '' ) ;
const mirroredSymbol = String( pair.mirroredSymbol || '' ) ;
if ( !enabledCanonical.has( canonicalSymbol) ) {
errors.push( ` transportPairs[ ${ pair .key } ] uses canonicalSymbol ${ canonicalSymbol } which is not enabled` ) ;
}
if ( !enabledChains.has( destinationChainId) ) {
errors.push( ` transportPairs[ ${ pair .key } ] uses destinationChainId ${ destinationChainId } which is not enabled` ) ;
}
const peer = peersByKey.get( String( pair.peerKey || '' ) ) ;
if ( !peer) {
errors.push( ` transportPairs[ ${ pair .key } ] is missing approved bridge peer ${ pair .peerKey } ` ) ;
} else {
if ( !refConfigured( peer.l1Bridge) ) {
errors.push( ` approvedBridgePeers[ ${ peer .key } ] is missing l1Bridge wiring` ) ;
}
if ( !refConfigured( peer.l2Bridge) ) {
errors.push( ` approvedBridgePeers[ ${ peer .key } ] is missing l2Bridge wiring` ) ;
}
}
const maxOutstanding = pair.maxOutstanding && typeof pair.maxOutstanding = = = 'object' ? pair.maxOutstanding : null;
if ( !maxOutstanding || ( !maxOutstanding.amount && !maxOutstanding.env) ) {
errors.push( ` transportPairs[ ${ pair .key } ] is missing maxOutstanding amount/env` ) ;
}
const mappingToken = getMappingToken( canonicalChainId, destinationChainId, pair.mappingKey) ;
if ( !mappingToken) {
errors.push( ` transportPairs[ ${ pair .key } ] mappingKey ${ pair .mappingKey } is missing from token-mapping-multichain.json` ) ;
} else {
if ( !isNonZeroAddress( mappingToken.addressFrom) ) {
errors.push( ` transportPairs[ ${ pair .key } ] has invalid canonical addressFrom in token-mapping-multichain.json` ) ;
}
if ( !isNonZeroAddress( mappingToken.addressTo) ) {
errors.push( ` transportPairs[ ${ pair .key } ] mapping exists but cW pair is not deployed ( addressTo missing/zero) ` ) ;
}
}
const deploymentChain = deployment.chains?.[ String( destinationChainId) ] ;
const deployedMirror = deploymentChain?.cwTokens?.[ mirroredSymbol] ;
if ( !deploymentChain || !isNonZeroAddress( deployedMirror) ) {
errors.push( ` transportPairs[ ${ pair .key } ] mapping exists but deployment-status.json has no deployed ${ mirroredSymbol } for chain ${ destinationChainId } ` ) ;
} else if ( mappingToken && normalizeAddress( deployedMirror) != = normalizeAddress( mappingToken.addressTo) ) {
errors.push( ` transportPairs[ ${ pair .key } ] deployment-status.json ${ mirroredSymbol } does not match token-mapping-multichain.json addressTo` ) ;
}
if ( ( pair.publicPoolKeys || [ ] ) .length > 0) {
for ( const publicPoolKey of pair.publicPoolKeys) {
if ( !publicPoolsByKey.has( String( publicPoolKey) ) ) {
errors.push( ` transportPairs[ ${ pair .key } ] references missing public pool key ${ publicPoolKey } ` ) ;
}
}
}
if ( pair.reserveVerifierKey) {
const verifier = reserveVerifiers[ pair.reserveVerifierKey] ;
if ( !verifier) {
errors.push( ` transportPairs[ ${ pair .key } ] requires missing reserve verifier ${ pair .reserveVerifierKey } ` ) ;
} else {
if ( !refConfigured( verifier.bridgeRef) ) {
errors.push( ` reserveVerifiers.${ pair .reserveVerifierKey } is missing bridgeRef wiring` ) ;
}
if ( !refConfigured( verifier.verifierRef) ) {
errors.push( ` reserveVerifiers.${ pair .reserveVerifierKey } is missing verifierRef wiring` ) ;
}
if ( verifier.requireVaultBacking && !refConfigured( verifier.vaultRef) ) {
errors.push( ` reserveVerifiers.${ pair .reserveVerifierKey } requires vault backing but vaultRef is unset ` ) ;
}
if ( verifier.requireReserveSystemBalance && !refConfigured( verifier.reserveSystemRef) ) {
errors.push( ` reserveVerifiers.${ pair .reserveVerifierKey } requires reserve-system balance checks but reserveSystemRef is unset ` ) ;
}
}
}
}
for ( const pool of active.publicPools || [ ] ) {
if ( pool.active = = = true ) {
if ( !isNonZeroAddress( pool.poolAddress) ) {
errors.push( ` publicPools[ ${ pool .key } ] is active but has no poolAddress` ) ;
continue ;
}
const deploymentChain = deployment.chains?.[ String( pool.chainId) ] ;
const deployedPools = Array.isArray( deploymentChain?.pmmPools) ? deploymentChain.pmmPools : [ ] ;
const deploymentMatch = deployedPools.some( ( entry) = > normalizeAddress( entry?.poolAddress) = = = normalizeAddress( pool.poolAddress) ) ;
if ( !deploymentMatch) {
errors.push( ` publicPools[ ${ pool .key } ] is active but deployment-status.json does not contain its poolAddress` ) ;
}
}
}
for ( const [ chainIdKey, deploymentChain] of Object.entries( deployment.chains || { } ) ) {
const destinationChainId = Number( chainIdKey) ;
if ( destinationChainId = = = canonicalChainId) continue ;
if ( deploymentChain?.bridgeAvailable != = true ) continue ;
const mappingPair = getMappingPair( canonicalChainId, destinationChainId) ;
if ( !mappingPair) continue ;
let compatible = true;
for ( const token of enabledCanonicalTokens) {
const mappingKey = String( token.mappingKey || '' ) ;
const mirroredSymbol = String( token.mirroredSymbol || '' ) ;
const mappingToken = mappingKey ? ( mappingPair.tokens || [ ] ) .find( ( entry) = > entry.key = = = mappingKey) : null;
const deployedMirror = deploymentChain?.cwTokens?.[ mirroredSymbol] ;
const expectedPoolKey = getExpectedPoolKey( destinationChainId, mirroredSymbol) ;
if (
!mappingKey ||
!mappingToken ||
!isNonZeroAddress( mappingToken.addressTo) ||
!isNonZeroAddress( deployedMirror) ||
normalizeAddress( mappingToken.addressTo) != = normalizeAddress( deployedMirror) ||
!expectedPoolKey
) {
compatible = false;
break;
}
}
if ( !compatible) continue ;
const enabledChain = enabledChainsArray.find( ( chain) = > Number( chain.chainId) = = = destinationChainId) ;
if ( !enabledChain) {
errors.push( ` compatible destination chain ${ destinationChainId } ( ${ deploymentChain ?.name || 'unknown' } ) is missing from enabledDestinationChains` ) ;
continue ;
}
for ( const token of enabledCanonicalTokens) {
const expectedPairKey = ` ${ canonicalChainId } -${ destinationChainId } -${ token .symbol } -${ token .mirroredSymbol } ` ;
const expectedPoolKey = getExpectedPoolKey( destinationChainId, String( token.mirroredSymbol || '' ) ) ;
const pair = transportPairsByKey.get( expectedPairKey) ;
if ( !pair) {
errors.push( ` compatible destination chain ${ destinationChainId } is missing transport pair ${ expectedPairKey } ` ) ;
continue ;
}
if ( expectedPoolKey && !publicPoolsByKey.has( expectedPoolKey) ) {
errors.push( ` compatible destination chain ${ destinationChainId } is missing public pool placeholder ${ expectedPoolKey } ` ) ;
}
if ( expectedPoolKey && !( pair.publicPoolKeys || [ ] ) .includes( expectedPoolKey) ) {
errors.push( ` transportPairs[ ${ pair .key } ] must include the pool-matrix first-hop key ${ expectedPoolKey } ` ) ;
}
}
}
if ( errors.length > 0) {
console.error( errors.join( '\n' ) ) ;
process.exit( 1) ;
}
NODE
then
log_ok "gru-transport-active.json: overlay cross-checks passed"
else
log_err "gru-transport-active.json: overlay cross-checks failed"
ERRORS = $(( ERRORS + 1 ))
fi
else
log_err "Node.js is required to validate gru-transport-active.json cross-file wiring"
ERRORS = $(( ERRORS + 1 ))
fi
else
log_err "Missing config/gru-transport-active.json"
ERRORS = $(( ERRORS + 1 ))
fi
2026-03-31 22:52:53 -07:00
if [ [ -f " $PROJECT_ROOT /config/gru-governance-supervision-profile.json " ] ] ; then
log_ok "Found: config/gru-governance-supervision-profile.json"
if command -v jq & >/dev/null; then
if jq -e '
( .profileId | type = = "string" )
and ( .requiredAssetMetadata | type = = "array" )
and ( .roles.tokenRoles | type = = "array" )
and ( .roles.registryRoles | type = = "array" )
and ( .roles.governanceRoles | type = = "array" )
and ( .storageNamespaces | type = = "object" )
and ( .proposalPolicy.defaultMinimumUpgradeNoticePeriodSeconds | type = = "number" )
2026-04-01 11:28:41 -07:00
and ( .proposalPolicy.assetScopeRequiredForUpgradeSensitiveChanges = = true )
and ( .proposalPolicy.jurisdictionDerivedFromRegistryAssetState = = true )
and ( .proposalPolicy.jurisdictionTransitionRequiresBothAuthorities = = true )
and ( .proposalPolicy.proposalEntryPoint = = "GovernanceController.proposeForAsset" )
and ( .proposalPolicy.manualJurisdictionTaggingAllowed = = false )
and ( .proposalPolicy.jurisdictionPolicyEntryPoints | type = = "array" )
and ( .emergencyPolicy.manualAdminPathsRemainAvailable = = true )
and ( ( .emergencyPolicy.authorizedRoles | index( "EMERGENCY_ADMIN_ROLE" ) ) != null)
2026-03-31 22:52:53 -07:00
' " $PROJECT_ROOT /config/gru-governance-supervision-profile.json " & >/dev/null; then
log_ok "gru-governance-supervision-profile.json: top-level structure is valid"
else
log_err "gru-governance-supervision-profile.json: invalid top-level structure"
ERRORS = $(( ERRORS + 1 ))
fi
fi
fi
2026-02-21 15:46:06 -08:00
[ [ -f " $PROJECT_ROOT /config/smart-contracts-master.json " ] ] && log_ok "Found: config/smart-contracts-master.json" || true
2026-03-02 11:37:34 -08:00
# Token lists (Uniswap format): validate structure if present
for list in token-lists/lists/dbis-138.tokenlist.json token-lists/lists/cronos.tokenlist.json token-lists/lists/all-mainnet.tokenlist.json; do
if [ [ -f " $PROJECT_ROOT / $list " ] ] && command -v jq & >/dev/null; then
if jq -e '(.tokens | type == "array") and (.tokens | length > 0)' " $PROJECT_ROOT / $list " & >/dev/null; then
log_ok " Token list valid: $list "
else
log_err " Token list invalid or empty: $list "
ERRORS = $(( ERRORS + 1 ))
fi
fi
done
# DUAL_CHAIN config (explorer deploy source)
if [ [ -f " $PROJECT_ROOT /explorer-monorepo/backend/api/rest/config/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json " ] ] && command -v jq & >/dev/null; then
if jq -e '(.tokens | type == "array") and (.tokens | length > 0)' " $PROJECT_ROOT /explorer-monorepo/backend/api/rest/config/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json " & >/dev/null; then
log_ok "DUAL_CHAIN_TOKEN_LIST valid"
else
log_err "DUAL_CHAIN_TOKEN_LIST invalid or empty"
ERRORS = $(( ERRORS + 1 ))
fi
fi
2026-03-27 18:51:02 -07:00
# Public-sector program manifest (served by phoenix-deploy-api GET /api/v1/public-sector/programs)
if [ [ -f " $PROJECT_ROOT /config/public-sector-program-manifest.json " ] ] ; then
log_ok "Found: config/public-sector-program-manifest.json"
if command -v jq & >/dev/null; then
if jq -e '
( .schemaVersion | type = = "string" )
and ( .programs | type = = "array" )
and ( .programs | length > 0)
and ( ( .programs | map( .id) | unique | length) = = ( .programs | length) )
' " $PROJECT_ROOT /config/public-sector-program-manifest.json " & >/dev/null; then
log_ok "public-sector-program-manifest.json: schemaVersion, programs[], unique .id"
else
log_err "public-sector-program-manifest.json: invalid structure or duplicate program ids"
ERRORS = $(( ERRORS + 1 ))
fi
fi
else
log_err "Missing config/public-sector-program-manifest.json"
ERRORS = $(( ERRORS + 1 ))
fi
# Proxmox operational template (VMID/IP/FQDN mirror; see docs/03-deployment/PROXMOX_VE_OPERATIONAL_DEPLOYMENT_TEMPLATE.md)
if [ [ -f " $PROJECT_ROOT /config/proxmox-operational-template.json " ] ] ; then
log_ok "Found: config/proxmox-operational-template.json"
if command -v jq & >/dev/null; then
if jq -e '
( .schemaVersion | type = = "string" )
and ( .network.management_lan.gateway | type = = "string" )
and ( .proxmox_nodes | type = = "array" )
and ( .proxmox_nodes | length >= 1)
and ( .services | type = = "array" )
and ( .services | length >= 1)
' " $PROJECT_ROOT /config/proxmox-operational-template.json " & >/dev/null; then
log_ok "proxmox-operational-template.json: schema, network, nodes, services"
else
log_err "proxmox-operational-template.json: invalid top-level structure"
ERRORS = $(( ERRORS + 1 ))
fi
fi
else
log_err "Missing config/proxmox-operational-template.json"
ERRORS = $(( ERRORS + 1 ))
fi
chore: sync docs, config schemas, scripts, and meta task alignment
- Institutional / JVMTM / reserve-provenance / GRU transport + standards JSON
- Validation and verify scripts (Blockscout labels, x402, GRU preflight, P1 local path)
- Wormhole wiring in AGENTS, MCP_SETUP, MASTER_INDEX, 04-configuration README
- Meta docs, integration gaps, live verification log, architecture updates
- CI validate-config workflow updates
Operator/LAN items, submodule working trees, and public token-aggregation edge
routes remain follow-up (see TODOS_CONSOLIDATED P1).
Made-with: Cursor
2026-03-31 22:31:39 -07:00
if [ [ -f " $PROJECT_ROOT /config/gru-iso4217-currency-manifest.json " ] ] ; then
log_ok "Found: config/gru-iso4217-currency-manifest.json"
if command -v jq & >/dev/null; then
if jq -e '
( .name | type = = "string" )
and ( .version | type = = "string" )
and ( .updated | type = = "string" )
and ( .canonicalChainId | type = = "number" )
and ( .currencies | type = = "array" )
and ( ( .currencies | length) > 0)
and ( ( .currencies | map( .code) | unique | length) = = ( .currencies | length) )
and (
all( .currencies[ ] ;
( .code | type = = "string" )
and ( ( .code | length) >= 3)
and ( .name | type = = "string" )
and ( .type = = "fiat" or .type = = "commodity" )
and ( ( .minorUnits = = null) or ( .minorUnits | type = = "number" ) )
and ( .status.planned | type = = "boolean" )
and ( .status.deployed | type = = "boolean" )
and ( .status.transportActive | type = = "boolean" )
and ( .status.x402Ready | type = = "boolean" )
and ( .canonicalAssets | type = = "object" )
)
)
' " $PROJECT_ROOT /config/gru-iso4217-currency-manifest.json " & >/dev/null; then
log_ok "gru-iso4217-currency-manifest.json: top-level manifest structure is valid"
else
log_err "gru-iso4217-currency-manifest.json: invalid top-level structure"
ERRORS = $(( ERRORS + 1 ))
fi
fi
fi
if [ [ -f " $PROJECT_ROOT /config/gru-standards-profile.json " ] ] ; then
log_ok "Found: config/gru-standards-profile.json"
if command -v jq & >/dev/null; then
if jq -e '
( .name | type = = "string" )
and ( .profileId | type = = "string" )
and ( .version | type = = "string" )
and ( .updated | type = = "string" )
and ( .canonicalChainId | type = = "number" )
and ( .scope | type = = "object" )
and ( .paymentProfiles | type = = "array" )
and ( .baseTokenStandards | type = = "array" )
and ( .transportAndWrapperStandards | type = = "array" )
and ( .governanceAndPolicyStandards | type = = "array" )
' " $PROJECT_ROOT /config/gru-standards-profile.json " & >/dev/null; then
log_ok "gru-standards-profile.json: top-level standards profile structure is valid"
else
log_err "gru-standards-profile.json: invalid top-level structure"
ERRORS = $(( ERRORS + 1 ))
fi
if jq -e '
( .canonicalChainId = = $activeChain )
and ( .canonicalChainId = = $manifestChain )
and ( .references.transportOverlay = = "config/gru-transport-active.json" )
and ( .references.currencyManifest = = "config/gru-iso4217-currency-manifest.json" )
2026-03-31 22:52:53 -07:00
and ( .references.governanceSupervisionProfile = = "config/gru-governance-supervision-profile.json" )
and ( .references.storageGovernanceDoc = = "docs/04-configuration/GRU_STORAGE_GOVERNANCE_AND_SUPERVISION_STANDARD.md" )
chore: sync docs, config schemas, scripts, and meta task alignment
- Institutional / JVMTM / reserve-provenance / GRU transport + standards JSON
- Validation and verify scripts (Blockscout labels, x402, GRU preflight, P1 local path)
- Wormhole wiring in AGENTS, MCP_SETUP, MASTER_INDEX, 04-configuration README
- Meta docs, integration gaps, live verification log, architecture updates
- CI validate-config workflow updates
Operator/LAN items, submodule working trees, and public token-aggregation edge
routes remain follow-up (see TODOS_CONSOLIDATED P1).
Made-with: Cursor
2026-03-31 22:31:39 -07:00
' \
--argjson activeChain " $( jq -r '.system.canonicalChainId' " $PROJECT_ROOT /config/gru-transport-active.json " ) " \
--argjson manifestChain " $( jq -r '.canonicalChainId' " $PROJECT_ROOT /config/gru-iso4217-currency-manifest.json " ) " \
" $PROJECT_ROOT /config/gru-standards-profile.json " & >/dev/null; then
2026-03-31 22:52:53 -07:00
log_ok "gru-standards-profile.json: canonical-chain and reference wiring matches active overlay + currency manifest + governance profile"
chore: sync docs, config schemas, scripts, and meta task alignment
- Institutional / JVMTM / reserve-provenance / GRU transport + standards JSON
- Validation and verify scripts (Blockscout labels, x402, GRU preflight, P1 local path)
- Wormhole wiring in AGENTS, MCP_SETUP, MASTER_INDEX, 04-configuration README
- Meta docs, integration gaps, live verification log, architecture updates
- CI validate-config workflow updates
Operator/LAN items, submodule working trees, and public token-aggregation edge
routes remain follow-up (see TODOS_CONSOLIDATED P1).
Made-with: Cursor
2026-03-31 22:31:39 -07:00
else
2026-03-31 22:52:53 -07:00
log_err "gru-standards-profile.json: canonical-chain or reference wiring does not match active overlay / currency manifest / governance profile"
chore: sync docs, config schemas, scripts, and meta task alignment
- Institutional / JVMTM / reserve-provenance / GRU transport + standards JSON
- Validation and verify scripts (Blockscout labels, x402, GRU preflight, P1 local path)
- Wormhole wiring in AGENTS, MCP_SETUP, MASTER_INDEX, 04-configuration README
- Meta docs, integration gaps, live verification log, architecture updates
- CI validate-config workflow updates
Operator/LAN items, submodule working trees, and public token-aggregation edge
routes remain follow-up (see TODOS_CONSOLIDATED P1).
Made-with: Cursor
2026-03-31 22:31:39 -07:00
ERRORS = $(( ERRORS + 1 ))
fi
fi
else
log_err "Missing config/gru-standards-profile.json"
ERRORS = $(( ERRORS + 1 ))
fi
2026-02-12 15:46:57 -08:00
fi
2026-03-02 11:37:34 -08:00
if [ [ -n " $OPTIONAL_ENV " ] ] ; then
for v in $OPTIONAL_ENV ; do
check_env " $v " || true
done
fi
2026-02-12 15:46:57 -08:00
chore: sync docs, config schemas, scripts, and meta task alignment
- Institutional / JVMTM / reserve-provenance / GRU transport + standards JSON
- Validation and verify scripts (Blockscout labels, x402, GRU preflight, P1 local path)
- Wormhole wiring in AGENTS, MCP_SETUP, MASTER_INDEX, 04-configuration README
- Meta docs, integration gaps, live verification log, architecture updates
- CI validate-config workflow updates
Operator/LAN items, submodule working trees, and public token-aggregation edge
routes remain follow-up (see TODOS_CONSOLIDATED P1).
Made-with: Cursor
2026-03-31 22:31:39 -07:00
# DBIS institutional Digital Master Plan example JSON
if [ [ -f " $PROJECT_ROOT /config/dbis-institutional/examples/trust.json " ] ] && [ [ -x " $SCRIPT_DIR /validate-dbis-institutional-json.sh " ] ] ; then
if bash " $SCRIPT_DIR /validate-dbis-institutional-json.sh " & >/dev/null; then
log_ok "DBIS institutional examples (JSON parse)"
else
log_err "DBIS institutional examples failed JSON parse"
ERRORS = $(( ERRORS + 1 ))
fi
fi
if command -v check-jsonschema & >/dev/null && [ [ -x " $SCRIPT_DIR /validate-dbis-institutional-schemas.sh " ] ] ; then
if SCHEMA_STRICT = 1 bash " $SCRIPT_DIR /validate-dbis-institutional-schemas.sh " & >/dev/null; then
log_ok "DBIS institutional JSON Schemas (settlement-event, address-registry-entry)"
else
log_err "DBIS institutional JSON Schema validation failed (pip install check-jsonschema)"
ERRORS = $(( ERRORS + 1 ))
fi
fi
2026-04-01 11:28:41 -07:00
if command -v node & >/dev/null && [ [ -f " $PROJECT_ROOT /scripts/verify/validate-address-registry-xe-aliases.mjs " ] ] ; then
if node " $PROJECT_ROOT /scripts/verify/validate-address-registry-xe-aliases.mjs " & >/dev/null; then
log_ok "DBIS institutional web3_eth_iban (XE) example aliases"
else
log_err "DBIS institutional web3_eth_iban validation failed (validate-address-registry-xe-aliases.mjs)"
ERRORS = $(( ERRORS + 1 ))
fi
fi
if command -v check-jsonschema & >/dev/null && [ [ -x " $SCRIPT_DIR /validate-naming-convention-registry-examples.sh " ] ] ; then
if SCHEMA_STRICT = 1 bash " $SCRIPT_DIR /validate-naming-convention-registry-examples.sh " & >/dev/null; then
log_ok "Naming conventions registry examples (UTRNF / DBIS token-registry-entry schema)"
else
log_err "Naming conventions registry example validation failed (see validate-naming-convention-registry-examples.sh)"
ERRORS = $(( ERRORS + 1 ))
fi
fi
chore: sync docs, config schemas, scripts, and meta task alignment
- Institutional / JVMTM / reserve-provenance / GRU transport + standards JSON
- Validation and verify scripts (Blockscout labels, x402, GRU preflight, P1 local path)
- Wormhole wiring in AGENTS, MCP_SETUP, MASTER_INDEX, 04-configuration README
- Meta docs, integration gaps, live verification log, architecture updates
- CI validate-config workflow updates
Operator/LAN items, submodule working trees, and public token-aggregation edge
routes remain follow-up (see TODOS_CONSOLIDATED P1).
Made-with: Cursor
2026-03-31 22:31:39 -07:00
if [ [ -f " $PROJECT_ROOT /config/smart-contracts-master.json " ] ] && command -v jq & >/dev/null && [ [ -x " $SCRIPT_DIR /validate-explorer-chain138-inventory.sh " ] ] ; then
if bash " $SCRIPT_DIR /validate-explorer-chain138-inventory.sh " & >/dev/null; then
log_ok "Explorer address-inventory Chain 138 vs smart-contracts-master.json"
else
log_err "Explorer address-inventory Chain 138 drift (see validate-explorer-chain138-inventory.sh)"
ERRORS = $(( ERRORS + 1 ))
fi
fi
2026-04-01 11:28:41 -07:00
if [ [ -d " $PROJECT_ROOT /config/xdc-zero " ] ] && [ [ -x " $SCRIPT_DIR /validate-xdc-zero-config.sh " ] ] ; then
if bash " $SCRIPT_DIR /validate-xdc-zero-config.sh " & >/dev/null; then
log_ok "config/xdc-zero/*.json (parse)"
else
log_err "config/xdc-zero JSON parse failed (validate-xdc-zero-config.sh)"
ERRORS = $(( ERRORS + 1 ))
fi
fi
2026-02-12 15:46:57 -08:00
if [ [ $ERRORS -gt 0 ] ] ; then
log_err " Validation failed with $ERRORS error(s). Set VALIDATE_REQUIRED_FILES='path1 path2' to require specific files. "
exit 1
fi
log_ok "Validation passed."
exit 0