Sync all local changes: docs, config, scripts, submodule refs, verification evidence
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
defiQUG
2026-02-21 15:46:06 -08:00
parent fbda1b4beb
commit bea1903ac9
1596 changed files with 93380 additions and 6194 deletions

View File

@@ -0,0 +1,182 @@
#!/usr/bin/env bash
# Create LXC 7804 (gov-portals-dev) and deploy the four Gov Portals (DBIS, ICCC, OMNL, XOM)
# Serving at dbis/iccc/omnl/xom.xom-dev.phoenix.sankofa.nexus via NPMplus
#
# Usage:
# From proxmox repo root, with SSH to Proxmox host:
# bash scripts/deployment/deploy-gov-portals-to-7804.sh [--create-only|--deploy-only]
#
# Prerequisites:
# - SSH to Proxmox host (default: r630-01)
# - gov-portals-monorepo cloned at /home/intlc/projects/gov-portals-monorepo (or GOV_PORTALS_SOURCE)
# - Gitea token in .env for clone (or public clone)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
source "$PROJECT_ROOT/config/ip-addresses.conf" 2>/dev/null || true
[ -f "$PROJECT_ROOT/.env" ] && set +u && source "$PROJECT_ROOT/.env" 2>/dev/null || true && set -u
# Gov Portals dev VM (7804) - Sankofa/Phoenix range
VMID_GOV_PORTALS=7804
IP_GOV_PORTALS_DEV="${IP_GOV_PORTALS_DEV:-192.168.11.54}"
HOSTNAME_GOV_PORTALS="gov-portals-dev"
PROXMOX_NODE="${PROXMOX_NODE:-r630-01}"
PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.11}"
STORAGE="${STORAGE:-local-lvm}"
TEMPLATE="${TEMPLATE:-local:vztmpl/debian-12-standard_12.12-1_amd64.tar.zst}"
GATEWAY="${GATEWAY:-192.168.11.1}"
NETWORK="${NETWORK:-vmbr0}"
# Source of gov-portals-monorepo (local path to rsync, or git URL)
GOV_PORTALS_SOURCE="${GOV_PORTALS_SOURCE:-/home/intlc/projects/gov-portals-monorepo}"
CREATE_ONLY=false
DEPLOY_ONLY=false
[[ "${1:-}" == "--create-only" ]] && CREATE_ONLY=true
[[ "${1:-}" == "--deploy-only" ]] && DEPLOY_ONLY=true
log() { echo "[$(date +%H:%M:%S)] $*"; }
run_ssh() { ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new root@$PROXMOX_HOST "$@"; }
run_ct() { run_ssh "pct exec $VMID_GOV_PORTALS -- $@"; }
# Create LXC 7804
create_container() {
if run_ssh "pct list 2>/dev/null | grep -q '^$VMID_GOV_PORTALS '"; then
log "Container $VMID_GOV_PORTALS already exists"
return 0
fi
log "Creating LXC $VMID_GOV_PORTALS ($HOSTNAME_GOV_PORTALS) on $PROXMOX_NODE..."
run_ssh "pct create $VMID_GOV_PORTALS $TEMPLATE \
--hostname $HOSTNAME_GOV_PORTALS \
--memory 2048 \
--cores 2 \
--rootfs $STORAGE:20 \
--net0 name=eth0,bridge=$NETWORK,ip=$IP_GOV_PORTALS_DEV/24,gw=$GATEWAY \
--description 'Gov Portals dev - DBIS, ICCC, OMNL, XOM' \
--start 1 \
--onboot 1 \
--unprivileged 1 \
--features nesting=1,keyctl=1"
log "Waiting for container to boot..."
sleep 10
}
# Deploy apps inside container
deploy_inside() {
log "Deploying gov-portals inside container..."
# Install Node 20, pnpm
run_ct "bash -lc 'command -v node >/dev/null 2>&1 || (curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs)'" 2>/dev/null || true
run_ct "bash -lc 'command -v pnpm >/dev/null 2>&1 || npm install -g pnpm'" 2>/dev/null || true
# Prepare deploy dir
run_ct "mkdir -p /srv/gov-portals"
run_ct "rm -rf /srv/gov-portals/.git /srv/gov-portals/DBIS /srv/gov-portals/ICCC /srv/gov-portals/OMNL /srv/gov-portals/XOM /srv/gov-portals/node_modules /srv/gov-portals/*/node_modules 2>/dev/null || true"
# Rsync monorepo (from host running this script)
if [ -d "$GOV_PORTALS_SOURCE" ]; then
log "Rsyncing gov-portals-monorepo to container..."
rsync -az --delete \
--exclude 'node_modules' \
--exclude '.next' \
--exclude '.git' \
"$GOV_PORTALS_SOURCE/" \
"root@$PROXMOX_HOST:/tmp/gov-portals-rsync/" 2>/dev/null || {
log "Rsync to Proxmox host failed - will try git clone inside container"
}
if run_ssh "test -d /tmp/gov-portals-rsync/packages"; then
run_ssh "pct push $VMID_GOV_PORTALS /tmp/gov-portals-rsync /srv/gov-portals --recursive" 2>/dev/null || true
fi
fi
# Ensure we have submodules - clone if rsync didn't work
run_ct "bash -c '
cd /srv/gov-portals 2>/dev/null || mkdir -p /srv/gov-portals && cd /srv/gov-portals
if [ ! -f package.json ]; then
apt-get update -qq && apt-get install -y -qq git
git clone --recurse-submodules https://gitea.d-bis.org/Gov_Web_Portals/gov-portals-monorepo.git .
fi
if [ -d .git ] && [ ! -d DBIS/.git ]; then
git submodule update --init --recursive
fi
'"
# Install deps and build each portal
run_ct "bash -c '
cd /srv/gov-portals
export PATH=\"/usr/bin:/usr/local/bin:\$PATH\"
pnpm install --frozen-lockfile 2>/dev/null || pnpm install
for portal in DBIS ICCC OMNL XOM; do
if [ -d \"\$portal\" ]; then
echo \"Building \$portal...\"
(cd \"\$portal\" && pnpm run build) 2>/dev/null || true
fi
done
'"
# Create systemd services or PM2 - use simple node/next start
log "Creating startup script and systemd service..."
run_ct "bash -c '
cat > /srv/gov-portals/start-portals.sh << \"SCRIPT\"
#!/bin/bash
cd /srv/gov-portals
export NODE_ENV=production
PORT=3001 node DBIS/node_modules/next/dist/bin/next start -p 3001 &
PORT=3002 node ICCC/node_modules/next/dist/bin/next start -p 3002 &
PORT=3003 node OMNL/node_modules/next/dist/bin/next start -p 3003 &
PORT=3004 node XOM/node_modules/next/dist/bin/next start -p 3004 &
wait
SCRIPT
chmod +x /srv/gov-portals/start-portals.sh
'"
# Create systemd services for each portal
run_ct "bash -c '
for spec in DBIS:3001 ICCC:3002 OMNL:3003 XOM:3004; do
portal=\${spec%%:*}
port=\${spec##*:}
cat > /etc/systemd/system/gov-portal-\${portal}.service << EOF
[Unit]
Description=Gov Portal \$portal
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/srv/gov-portals/\$portal
Environment=NODE_ENV=production
Environment=PORT=\$port
ExecStart=/usr/bin/node /srv/gov-portals/\$portal/node_modules/next/dist/bin/next start -p \$port
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable gov-portal-\${portal}
systemctl restart gov-portal-\${portal} 2>/dev/null || systemctl start gov-portal-\${portal}
done
'" 2>/dev/null || log "Services may need manual start - run: pct exec 7804 -- systemctl start gov-portal-DBIS gov-portal-ICCC gov-portal-OMNL gov-portal-XOM"
log "Deployment complete. Portals should be starting on ports 3001-3004."
}
# Main
if [ "$DEPLOY_ONLY" = true ]; then
deploy_inside
elif [ "$CREATE_ONLY" = true ]; then
create_container
else
create_container
deploy_inside
fi
echo ""
echo "Gov Portals dev (7804) at $IP_GOV_PORTALS_DEV"
echo "Next: Run add-gov-portals-xom-dev-proxy-hosts.sh to add NPMplus proxy hosts"
echo " dbis.xom-dev.phoenix.sankofa.nexus → :3001"
echo " iccc.xom-dev.phoenix.sankofa.nexus → :3002"
echo " omnl.xom-dev.phoenix.sankofa.nexus → :3003"
echo " xom.xom-dev.phoenix.sankofa.nexus → :3004"

View File

@@ -0,0 +1,42 @@
#!/usr/bin/env bash
# Deploy a single contract to Chain 138 (dry-run by default).
# Usage: ./scripts/deployment/deploy-one-contract.sh <script_path> [--broadcast]
# Example: ./scripts/deployment/deploy-one-contract.sh script/DeployMulticall.s.sol:DeployMulticall --broadcast
# Requires: smom-dbis-138/.env with PRIVATE_KEY, RPC_URL_138 (Chain 138 Core)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
SMOM="${SMOM_DIR:-${PROJECT_ROOT}/smom-dbis-138}"
[[ -f "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" ]] && source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true
[[ -f "${SMOM}/.env" ]] && source "${SMOM}/.env" 2>/dev/null || true
GAS_PRICE="${GAS_PRICE:-1000000000}"
RPC_URL="${RPC_URL_138:-http://192.168.11.211:8545}"
SCRIPT_SPEC="${1:-}"
if [[ -z "$SCRIPT_SPEC" ]]; then
echo "Usage: $0 <script_path> [--broadcast]"
echo "Example: $0 script/DeployMulticall.s.sol:DeployMulticall --broadcast"
exit 1
fi
BROADCAST=""
[[ "${2:-}" = "--broadcast" ]] && BROADCAST="--broadcast --private-key ${PRIVATE_KEY:?PRIVATE_KEY required for broadcast}"
cd "$SMOM"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Deploy one contract: $SCRIPT_SPEC"
echo "RPC: $RPC_URL | Gas price: $GAS_PRICE"
[[ -n "$BROADCAST" ]] && echo "Mode: BROADCAST (on-chain)" || echo "Mode: DRY RUN (no tx)"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
forge script "$SCRIPT_SPEC" \
--rpc-url "$RPC_URL" \
--with-gas-price "$GAS_PRICE" \
$BROADCAST
echo ""
echo "Done. If you used --broadcast, note the deployed address(es) and run verification next."

View File

@@ -0,0 +1,77 @@
#!/usr/bin/env bash
# Deploy TransactionMirror to Chain 138.
# Use this when forge script DeployTransactionMirror.s.sol fails with constructor-args decode (forge create works).
# Usage: ./scripts/deployment/deploy-transaction-mirror-chain138.sh [--dry-run]
# --dry-run Print forge create command and exit 0 (no deploy).
# Requires: smom-dbis-138/.env with PRIVATE_KEY, RPC_URL_138 or RPC_URL (Chain 138 Core). Optional: MIRROR_ADMIN.
# Also sources load-project-env (secure-secrets, config). Must run from a host that can reach RPC (e.g. LAN to 192.168.11.211:8545).
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
SMOM="${SMOM_DIR:-${PROJECT_ROOT}/smom-dbis-138}"
DRY_RUN=false
for a in "$@"; do [[ "$a" == "--dry-run" ]] && DRY_RUN=true && break; done
[[ -f "${SCRIPT_DIR}/../lib/load-project-env.sh" ]] && source "${SCRIPT_DIR}/../lib/load-project-env.sh" 2>/dev/null || true
[[ -f "${SMOM}/.env" ]] && set -a && source "${SMOM}/.env" 2>/dev/null && set +a || true
# RPC_URL_138 or RPC_URL (alias)
RPC="${RPC_URL_138:-${RPC_URL:-http://192.168.11.211:8545}}"
export RPC_URL_138="$RPC"
export ETH_RPC_URL="$RPC"
GAS_PRICE="${GAS_PRICE:-1000000000}"
if ! $DRY_RUN && [[ -z "${PRIVATE_KEY:-}" ]]; then
echo "ERROR: PRIVATE_KEY not set. Set in smom-dbis-138/.env"
exit 1
fi
if [[ "${PRIVATE_KEY#0x}" == "$PRIVATE_KEY" ]]; then
export PRIVATE_KEY="0x$PRIVATE_KEY"
fi
export PRIVATE_KEY # Ensure subshells/forge inherit it
# MIRROR_ADMIN or deployer address
if [[ -n "${MIRROR_ADMIN:-}" ]]; then
ADMIN="$MIRROR_ADMIN"
else
if $DRY_RUN; then ADMIN="<DEPLOYER_ADDRESS>"; else ADMIN=$(cast wallet address --private-key "$PRIVATE_KEY" 2>/dev/null) || { echo "ERROR: cast not found or PRIVATE_KEY invalid"; exit 1; }; fi
fi
if $DRY_RUN; then
echo "[dry-run] Would run: forge create ... TransactionMirror --constructor-args $ADMIN --rpc-url $RPC --legacy --gas-price $GAS_PRICE"
echo " Add TRANSACTION_MIRROR_ADDRESS=<deployed> to smom-dbis-138/.env after deploy."
exit 0
fi
echo "Deploying TransactionMirror to Chain 138 (admin=$ADMIN)"
echo " RPC=$RPC"
cd "$SMOM"
# Use forge script (DeployTransactionMirror.s.sol) — more reliable than forge create with env
out=$(env ETH_RPC_URL="$RPC" MIRROR_ADMIN="$ADMIN" forge script script/DeployTransactionMirror.s.sol:DeployTransactionMirror \
--rpc-url "$RPC" \
--broadcast \
--private-key "$PRIVATE_KEY" \
--legacy \
--gas-price "$GAS_PRICE" 2>&1) || { echo "$out"; echo "Run from a host on LAN that can reach $RPC"; exit 1; }
echo "$out"
addr=$(echo "$out" | grep -oE 'TransactionMirror deployed at: (0x[a-fA-F0-9]{40})' | sed 's/TransactionMirror deployed at: //')
if [[ -n "$addr" ]]; then
echo ""
echo "Deployed TransactionMirror at: $addr"
env_file="${SMOM}/.env"
if [[ -f "$env_file" ]]; then
if grep -q "^TRANSACTION_MIRROR_ADDRESS=" "$env_file" 2>/dev/null; then
sed -i "s|^TRANSACTION_MIRROR_ADDRESS=.*|TRANSACTION_MIRROR_ADDRESS=$addr|" "$env_file"
echo " Updated TRANSACTION_MIRROR_ADDRESS in $env_file"
else
echo "TRANSACTION_MIRROR_ADDRESS=$addr" >> "$env_file"
echo " Appended TRANSACTION_MIRROR_ADDRESS to $env_file"
fi
fi
fi
echo ""
echo "Done. Add TRANSACTION_MIRROR_ADDRESS=<deployed> to smom-dbis-138/.env if not already set."

View File

@@ -0,0 +1,90 @@
#!/usr/bin/env bash
# R15: Deployment automation — check env → deploy (optional) → verify → update config.
# Usage: ./scripts/deployment/deploy-verify-chain138.sh [--dry-run] [--deploy] [--verify-only]
# --dry-run Print steps only; do not run deploy or verify (exit 0).
# --deploy Run phased deploy (01_DeployCore, 02_DeployBridges) before verify. Omit to verify only.
# --verify-only Skip deploy; run on-chain check + Blockscout verification only.
# Requires: LAN/VPN to Chain 138 RPC and Blockscout. PRIVATE_KEY and RPC_URL_138 read from dotenv (root .env, then smom-dbis-138/.env).
# See: docs/03-deployment/CONTRACT_DEPLOYMENT_RUNBOOK.md
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
cd "$PROJECT_ROOT"
# Load PRIVATE_KEY and RPC from dotenv
[[ -f "${SCRIPT_DIR}/../lib/load-project-env.sh" ]] && source "${SCRIPT_DIR}/../lib/load-project-env.sh" 2>/dev/null || true
DRY_RUN=false
DO_DEPLOY=false
VERIFY_ONLY=false
for a in "$@"; do
[[ "$a" == "--dry-run" ]] && DRY_RUN=true
[[ "$a" == "--deploy" ]] && DO_DEPLOY=true
[[ "$a" == "--verify-only" ]] && VERIFY_ONLY=true
done
echo "=== Deploy & Verify Chain 138 (R15) ==="
echo ""
if $DRY_RUN; then
echo "1. Check env: PRIVATE_KEY and RPC_URL_138 read from dotenv (smom-dbis-138/.env or root .env)"
echo "2. Config validation: bash scripts/validation/validate-config-files.sh"
echo "3. Deploy (if --deploy): cd smom-dbis-138 && bash scripts/deployment/deploy-contracts-unified.sh --mode ordered"
echo "4. On-chain check: bash scripts/verify/check-contracts-on-chain-138.sh"
echo "5. Blockscout verify: source smom-dbis-138/.env; bash scripts/verify/run-contract-verification-with-proxy.sh"
echo "6. Reconcile .env: bash scripts/verify/reconcile-env-canonical.sh --print (update smom-dbis-138/.env from output)"
echo ""
echo "Usage: $0 [--dry-run] [--deploy] [--verify-only]"
exit 0
fi
# 1. Env check (PRIVATE_KEY already loaded from dotenv above; re-source smom .env if present)
[[ -f "smom-dbis-138/.env" ]] && source smom-dbis-138/.env 2>/dev/null || true
PRIVATE_KEY="${PRIVATE_KEY:-${CHAIN138_PRIVATE_KEY:-}}"
# RPC_URL_138 = Chain 138 Core (load-project-env sets it from .env or config)
if [[ -z "${PRIVATE_KEY:-}" ]]; then
echo "PRIVATE_KEY (or CHAIN138_PRIVATE_KEY) not set. Set in smom-dbis-138/.env or root .env."
exit 1
fi
if [[ -z "${RPC_URL_138:-}" ]]; then
echo "RPC_URL_138 not set. Set in smom-dbis-138/.env or root .env (standard for Chain ID 138 RPC)."
exit 1
fi
echo "[OK] Env present (PRIVATE_KEY and RPC from dotenv)"
# 2. Config validation
echo "2. Config validation..."
bash scripts/validation/validate-config-files.sh
echo ""
# 3. Deploy (optional)
if $DO_DEPLOY && ! $VERIFY_ONLY; then
echo "3. Deploy (ordered)..."
(cd smom-dbis-138 && bash scripts/deployment/deploy-contracts-unified.sh --mode ordered)
echo ""
else
echo "3. Deploy skipped (use --deploy to run)"
fi
# 4. On-chain check
echo "4. On-chain check..."
SKIP_EXIT=1 bash scripts/verify/check-contracts-on-chain-138.sh || true
echo ""
# 5. Blockscout verification (may require LAN)
echo "5. Blockscout verification..."
source smom-dbis-138/.env 2>/dev/null || true
if bash scripts/verify/run-contract-verification-with-proxy.sh 2>/dev/null; then
echo "[OK] Verification run completed"
else
echo "[WARN] Verification failed or Blockscout unreachable (run from LAN). See CONTRACT_DEPLOYMENT_RUNBOOK."
fi
echo ""
# 6. Reconcile
echo "6. Reconcile .env (canonical list):"
bash scripts/verify/reconcile-env-canonical.sh --print
echo ""
echo "=== Done. Update smom-dbis-138/.env from reconcile output if needed. ==="