diff --git a/.claude/scripts/setup-runner.sh b/.claude/scripts/setup-runner.sh index 7429807441..b561aba718 100755 --- a/.claude/scripts/setup-runner.sh +++ b/.claude/scripts/setup-runner.sh @@ -3,7 +3,7 @@ # Generated: 2025-12-23 # # Usage: ./setup-runner.sh -# Where HOST_TYPE is one of: ai-lab, vps, cloudstartup, kvm4 +# Where HOST_TYPE is one of: ai-lab, vps, cloudstartup, kvm4, kvm4-1, kvm4-2, kvm2 set -e @@ -21,10 +21,13 @@ HOST_LABELS["ai-lab"]="self-hosted,ai-lab,gpu,Linux,X64" HOST_LABELS["vps"]="self-hosted,vps,Linux,X64" HOST_LABELS["cloudstartup"]="self-hosted,cloudstartup,staging,Linux,X64" HOST_LABELS["kvm4"]="self-hosted,kvm4,production,Linux,X64" +HOST_LABELS["kvm4-1"]="self-hosted,vps,kvm4,kvm4-1,production,Linux,X64" +HOST_LABELS["kvm4-2"]="self-hosted,vps,kvm4,kvm4-2,production,Linux,X64" +HOST_LABELS["kvm2"]="self-hosted,vps,kvm2,backup,Linux,X64" if [[ -z "$HOST_TYPE" ]] || [[ ! ${HOST_LABELS[$HOST_TYPE]+_} ]]; then echo "Usage: $0 " - echo "HOST_TYPE must be one of: ai-lab, vps, cloudstartup, kvm4" + echo "HOST_TYPE must be one of: ai-lab, vps, cloudstartup, kvm4, kvm4-1, kvm4-2, kvm2" exit 1 fi diff --git a/.github/workflows/build-images.yml b/.github/workflows/build-images.yml index 47b7320aab..b7bc95fbe2 100644 --- a/.github/workflows/build-images.yml +++ b/.github/workflows/build-images.yml @@ -19,7 +19,7 @@ env: jobs: setup-matrix: - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: @@ -47,6 +47,7 @@ jobs: runs-on: [self-hosted, Linux, X64] strategy: fail-fast: false + max-parallel: 4 matrix: ${{ fromJson(needs.setup-matrix.outputs.matrix) }} defaults: run: diff --git a/.github/workflows/codex-parity-advisory.yml b/.github/workflows/codex-parity-advisory.yml index b5c91a5b2a..0fa7e78cc0 100644 --- a/.github/workflows/codex-parity-advisory.yml +++ b/.github/workflows/codex-parity-advisory.yml @@ -11,6 +11,10 @@ on: permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + jobs: codex-parity-advisory: name: codex-parity-advisory diff --git a/.github/workflows/deploy-gateway-agent.yml b/.github/workflows/deploy-gateway-agent.yml index bac45422c7..4fcf29b486 100644 --- a/.github/workflows/deploy-gateway-agent.yml +++ b/.github/workflows/deploy-gateway-agent.yml @@ -32,8 +32,7 @@ env: jobs: validate: name: Validate Configuration - # PMOVES.AI: Use self-hosted runners for production CI - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest permissions: contents: read steps: @@ -177,9 +176,15 @@ jobs: - name: Verify secrets loaded run: | - secrets=$(curl -s http://localhost:8100/secrets) - echo "✓ Secrets endpoint response:" - echo "$secrets" | jq '.' + count=$(curl -sf http://localhost:8100/secrets | jq 'length' 2>/dev/null) || { + echo "✗ Failed to query secrets endpoint" + exit 1 + } + if [ "$count" -eq 0 ] 2>/dev/null; then + echo "✗ Zero secret keys loaded — check GitHub Secrets configuration" + exit 1 + fi + echo "✓ $count secret keys loaded" # ============================================================================ # Rollback diff --git a/.github/workflows/hardening-validation.yml b/.github/workflows/hardening-validation.yml index 76fca30227..0fee492ac5 100644 --- a/.github/workflows/hardening-validation.yml +++ b/.github/workflows/hardening-validation.yml @@ -31,7 +31,7 @@ jobs: # ============================================================================ validate-hardening: name: Validate Hardening Patterns - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest steps: - name: Harden Runner @@ -88,7 +88,7 @@ jobs: # ============================================================================ validate-dockerfiles: name: Validate Dockerfiles - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest strategy: fail-fast: false # Limit fan-out to reduce self-hosted queue contention. @@ -166,7 +166,7 @@ jobs: # ============================================================================ docker-bench: name: Docker Bench Security - runs-on: [self-hosted, Linux, X64] + runs-on: [self-hosted, Linux, X64, vps] steps: - name: Harden Runner @@ -200,7 +200,7 @@ jobs: # ============================================================================ validate-compose: name: Validate Compose Files - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest steps: - name: Harden Runner @@ -277,7 +277,7 @@ jobs: # ============================================================================ summary: name: Validation Summary - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest needs: [validate-hardening, validate-dockerfiles, validate-compose] if: always() diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index c7b05dd90c..3a1255e44a 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -29,8 +29,7 @@ concurrency: jobs: tests: - # PMOVES.AI: Use self-hosted runners for production CI - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest permissions: contents: read actions: read diff --git a/.github/workflows/self-hosted-builds-hardened.yml b/.github/workflows/self-hosted-builds-hardened.yml index 190d9f5459..1c3d867b15 100644 --- a/.github/workflows/self-hosted-builds-hardened.yml +++ b/.github/workflows/self-hosted-builds-hardened.yml @@ -183,6 +183,7 @@ jobs: runs-on: [self-hosted, Linux, X64] strategy: fail-fast: false + max-parallel: 3 matrix: service: - name: pmoves-yt diff --git a/.github/workflows/sql-policy-lint.yml b/.github/workflows/sql-policy-lint.yml index 3962f0acb2..9efe4e3118 100644 --- a/.github/workflows/sql-policy-lint.yml +++ b/.github/workflows/sql-policy-lint.yml @@ -23,8 +23,7 @@ permissions: jobs: lint: - # PMOVES.AI: Use self-hosted runners for production CI - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest permissions: contents: read steps: diff --git a/.github/workflows/sync-secrets-local.yml b/.github/workflows/sync-secrets-local.yml index bda3dd5183..4886ea4aea 100644 --- a/.github/workflows/sync-secrets-local.yml +++ b/.github/workflows/sync-secrets-local.yml @@ -106,6 +106,14 @@ jobs: GHCR_USERNAME: ${{ secrets.GHCR_USERNAME }} CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + # Hostinger VPS + HOSTINGER_API_TOKEN: ${{ secrets.HOSTINGER_API_TOKEN }} + HOSTINGER_KVM4_1_IP: ${{ secrets.HOSTINGER_KVM4_1_IP }} + HOSTINGER_KVM4_1_USER: ${{ secrets.HOSTINGER_KVM4_1_USER }} + HOSTINGER_KVM4_2_IP: ${{ secrets.HOSTINGER_KVM4_2_IP }} + HOSTINGER_KVM4_2_USER: ${{ secrets.HOSTINGER_KVM4_2_USER }} + HOSTINGER_KVM2_IP: ${{ secrets.HOSTINGER_KVM2_IP }} + HOSTINGER_KVM2_USER: ${{ secrets.HOSTINGER_KVM2_USER }} run: | import json, os, sys from pathlib import Path diff --git a/.github/workflows/webhook-smoke.yml b/.github/workflows/webhook-smoke.yml index 8167bb7747..07b5d7ea55 100644 --- a/.github/workflows/webhook-smoke.yml +++ b/.github/workflows/webhook-smoke.yml @@ -17,9 +17,13 @@ on: permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: smoke: - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest steps: - name: Harden Runner uses: step-security/harden-runner@v2 diff --git a/.github/workflows/yt-dlp-bump.yml b/.github/workflows/yt-dlp-bump.yml index c46d833b3b..c97e3e9714 100644 --- a/.github/workflows/yt-dlp-bump.yml +++ b/.github/workflows/yt-dlp-bump.yml @@ -19,8 +19,7 @@ permissions: jobs: bump-yt-dlp: - # PMOVES.AI: Use self-hosted runners for production CI - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v6 @@ -38,6 +37,12 @@ jobs: fi echo "version=$latest" >> $GITHUB_OUTPUT + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + - name: Build pmoves-yt with bumped yt-dlp uses: docker/build-push-action@v6 with: diff --git a/.gitignore b/.gitignore index 621e0f37a8..4a66dadf9f 100644 --- a/.gitignore +++ b/.gitignore @@ -154,6 +154,16 @@ pmoves/env.jellyfin-ai pmoves/env.supa.runtime.bak.* +# ============================================================================= +# Terraform +# ============================================================================= +*.tfvars +*.tfvars.json +!*.tfvars.example +.terraform/ +*.tfstate +*.tfstate.* + # Windows desktop.ini Thumbs.db diff --git a/deploy/provision/hostinger-kvm-setup.sh b/deploy/provision/hostinger-kvm-setup.sh new file mode 100644 index 0000000000..6f58da9bc9 --- /dev/null +++ b/deploy/provision/hostinger-kvm-setup.sh @@ -0,0 +1,396 @@ +#!/bin/bash +# Hostinger KVM Provisioning Script +# +# Single script to provision a fresh Hostinger KVM as a PMOVES.AI node: +# 1. System update + hardening (ufw, fail2ban, sshd) +# 2. Docker + Docker Compose v2 +# 3. Tailscale mesh join +# 4. GitHub Actions runner (via install-hardened.sh) +# 5. /opt/pmoves work directory +# +# Usage: +# GITHUB_PAT=ghp_xxx TAILSCALE_AUTHKEY=tskey-xxx ./hostinger-kvm-setup.sh +# +# Prerequisites: +# - Fresh Ubuntu 22.04+ on Hostinger KVM +# - Root or sudo access +# - GITHUB_PAT with admin:org or repo scope +# - TAILSCALE_AUTHKEY (reusable, from https://login.tailscale.com/admin/settings/keys) + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +NODE_TYPE="${1:-}" + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +log_info() { echo -e "${GREEN}[INFO]${NC} $1"; } +log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +log_error() { echo -e "${RED}[ERROR]${NC} $1"; } +log_section() { echo -e "${BLUE}[====]${NC} $1"; } + +# Validate node type +validate_node_type() { + case "$NODE_TYPE" in + kvm4-1|kvm4-2|kvm2) ;; + *) + log_error "Invalid node type: '$NODE_TYPE'" + echo "Usage: $0 " + echo "" + echo "Node types:" + echo " kvm4-1 API Gateway (TensorZero, Agent Zero, Hi-RAG CPU)" + echo " kvm4-2 Data/Storage (Supabase, Qdrant, Neo4j, Meilisearch)" + echo " kvm2 Exit Node (Tailscale exit, Nginx, SSL termination)" + exit 1 + ;; + esac +} + +# Check required environment variables +check_env() { + log_section "Checking environment..." + + if [ -z "${GITHUB_PAT:-}" ]; then + log_error "GITHUB_PAT not set. Generate at: https://github.com/settings/tokens/new" + exit 1 + fi + + if [ -z "${TAILSCALE_AUTHKEY:-}" ]; then + log_warn "TAILSCALE_AUTHKEY not set. Tailscale setup will be skipped." + log_info "Generate at: https://login.tailscale.com/admin/settings/keys" + fi + + log_info "Node type: $NODE_TYPE" + log_info "Hostname: $(hostname)" + log_info "OS: $(. /etc/os-release && echo "$PRETTY_NAME")" +} + +# Step 1: System update + hardening +harden_system() { + log_section "Step 1: System hardening..." + + # Update packages + log_info "Updating system packages..." + apt-get update -qq + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y -qq + + # Install essentials + log_info "Installing essential packages..." + DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \ + curl wget git jq unzip htop \ + ufw fail2ban \ + ca-certificates gnupg lsb-release \ + uidmap dbus-user-session fuse-overlayfs slirp4netns + + # Configure UFW firewall + # NOTE: SSH port 22 is exposed publicly during provisioning, secured by: + # - Key-only auth (PasswordAuthentication no) + # - fail2ban with 5-attempt lockout + # - MaxAuthTries 3 + # Post-Tailscale, consider restricting to: ufw allow in on tailscale0 + # and removing public SSH: ufw delete allow 22/tcp + log_info "Configuring firewall (ufw)..." + ufw default deny incoming + ufw default allow outgoing + ufw allow 22/tcp comment "SSH" + + case "$NODE_TYPE" in + kvm4-1) + # API Gateway ports + ufw allow 8080/tcp comment "Agent Zero API" + ufw allow 8086/tcp comment "Hi-RAG v2 CPU" + ufw allow 3030/tcp comment "TensorZero Gateway" + ufw allow 8091/tcp comment "Archon API" + ufw allow 8100/tcp comment "Gateway Agent" + ;; + kvm4-2) + # Data services — only exposed within Tailscale mesh + ufw allow 4222/tcp comment "NATS" + ufw allow 6333/tcp comment "Qdrant" + ufw allow 7474/tcp comment "Neo4j HTTP" + ufw allow 7687/tcp comment "Neo4j Bolt" + ufw allow 7700/tcp comment "Meilisearch" + ufw allow 9090/tcp comment "Prometheus" + ufw allow 3000/tcp comment "Grafana" + ;; + kvm2) + # Exit node / proxy + ufw allow 80/tcp comment "HTTP" + ufw allow 443/tcp comment "HTTPS" + ;; + esac + + ufw --force enable + log_info "Firewall enabled" + + # Configure fail2ban + log_info "Configuring fail2ban..." + cat > /etc/fail2ban/jail.local <<'EOF' +[sshd] +enabled = true +port = ssh +filter = sshd +logpath = /var/log/auth.log +maxretry = 5 +bantime = 3600 +findtime = 600 +EOF + systemctl enable fail2ban + systemctl restart fail2ban + + # Harden SSH + log_info "Hardening SSH..." + sed -i 's/#PermitRootLogin yes/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config + sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config + sed -i 's/#MaxAuthTries 6/MaxAuthTries 3/' /etc/ssh/sshd_config + systemctl restart sshd + + log_info "System hardening complete" +} + +# Step 2: Docker + Docker Compose v2 +install_docker() { + log_section "Step 2: Installing Docker..." + + if command -v docker &>/dev/null; then + log_info "Docker already installed: $(docker --version)" + return 0 + fi + + # Install Docker using official script + curl -fsSL https://get.docker.com | sh + + # Add current user to docker group + usermod -aG docker "${SUDO_USER:-$USER}" + + # Install Docker Compose v2 plugin (if not bundled) + if ! docker compose version &>/dev/null; then + log_info "Installing Docker Compose v2 plugin..." + COMPOSE_VERSION="v2.27.0" + mkdir -p /usr/local/lib/docker/cli-plugins + curl -fsSL "https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" \ + -o /usr/local/lib/docker/cli-plugins/docker-compose + chmod +x /usr/local/lib/docker/cli-plugins/docker-compose + fi + + # Enable and start Docker + systemctl enable docker + systemctl start docker + + log_info "Docker installed: $(docker --version)" + log_info "Compose: $(docker compose version)" +} + +# Step 3: Tailscale mesh join +install_tailscale() { + log_section "Step 3: Installing Tailscale..." + + if [ -z "${TAILSCALE_AUTHKEY:-}" ]; then + log_warn "Skipping Tailscale (no TAILSCALE_AUTHKEY)" + return 0 + fi + + # Install Tailscale + if ! command -v tailscale &>/dev/null; then + curl -fsSL https://tailscale.com/install.sh | sh + fi + + # Join mesh with appropriate tags + local ts_args=( + --auth-key "$TAILSCALE_AUTHKEY" + --hostname "pmoves-${NODE_TYPE}" + --accept-routes + --accept-dns + ) + + # KVM2 is the exit node + if [ "$NODE_TYPE" = "kvm2" ]; then + log_info "Configuring as Tailscale exit node..." + # Enable IP forwarding for exit node + sysctl -w net.ipv4.ip_forward=1 + sysctl -w net.ipv6.conf.all.forwarding=1 + cat >> /etc/sysctl.d/99-tailscale.conf <<'EOF' +net.ipv4.ip_forward = 1 +net.ipv6.conf.all.forwarding = 1 +EOF + ts_args+=(--advertise-exit-node) + fi + + tailscale up "${ts_args[@]}" + + # Key expiry: tagged auth keys (--auth-key with tag:server) auto-disable expiry. + # For untagged keys, disable manually via Admin Console or Tailscale API: + # POST /api/v2/device/{deviceID}/key {"keyExpiryDisabled": true} + log_info "Key expiry is auto-disabled for tagged auth keys" + + # Verify connection + sleep 3 + if tailscale status &>/dev/null; then + local ts_ip + ts_ip=$(tailscale ip -4 2>/dev/null || echo "pending") + log_info "Tailscale connected: $ts_ip (pmoves-${NODE_TYPE})" + else + log_warn "Tailscale connection pending — may need admin approval" + fi +} + +# Step 4: GitHub Actions runner +install_runner() { + log_section "Step 4: Installing GitHub Actions runner..." + + # Create runner user if not exists + if ! id -u runner &>/dev/null; then + useradd -m -s /bin/bash runner + usermod -aG docker runner + fi + + # Use the hardened runner install script + local runner_script="${SCRIPT_DIR}/../runners/vps/install-hardened.sh" + if [ -f "$runner_script" ]; then + log_info "Using hardened runner install script..." + GITHUB_PAT="$GITHUB_PAT" \ + RUNNER_NAME="pmoves-${NODE_TYPE}" \ + GITHUB_ORG="POWERFULMOVES" \ + GITHUB_REPO="PMOVES.AI" \ + sudo -u runner bash "$runner_script" + else + log_warn "Hardened install script not found at: $runner_script" + log_info "Falling back to setup-runner.sh pattern..." + + local runner_dir="/home/runner/actions-runner-${NODE_TYPE}" + local runner_version="2.321.0" + local labels + + case "$NODE_TYPE" in + kvm4-1) labels="self-hosted,vps,kvm4,kvm4-1,production,Linux,X64" ;; + kvm4-2) labels="self-hosted,vps,kvm4,kvm4-2,production,Linux,X64" ;; + kvm2) labels="self-hosted,vps,kvm2,backup,Linux,X64" ;; + esac + + sudo -u runner mkdir -p "$runner_dir" + + # Get registration token + local reg_token + reg_token=$(curl -sf -X POST \ + -H "Authorization: token ${GITHUB_PAT}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/POWERFULMOVES/PMOVES.AI/actions/runners/registration-token" \ + | jq -r '.token') + + if [ -z "$reg_token" ] || [ "$reg_token" = "null" ]; then + log_error "Failed to get runner registration token" + return 1 + fi + + # Download and configure runner + cd "$runner_dir" + if [ ! -f "./config.sh" ]; then + curl -sL -o actions-runner.tar.gz \ + "https://github.com/actions/runner/releases/download/v${runner_version}/actions-runner-linux-x64-${runner_version}.tar.gz" + sudo -u runner tar xzf actions-runner.tar.gz + rm actions-runner.tar.gz + fi + + sudo ./bin/installdependencies.sh + + sudo -u runner ./config.sh \ + --url "https://github.com/POWERFULMOVES/PMOVES.AI" \ + --token "$reg_token" \ + --name "pmoves-${NODE_TYPE}-runner" \ + --labels "$labels" \ + --work "_work" \ + --replace \ + --unattended + + sudo ./svc.sh install runner + sudo ./svc.sh start + fi + + log_info "Runner installed for node: $NODE_TYPE" +} + +# Step 5: Create work directory +setup_workdir() { + log_section "Step 5: Setting up /opt/pmoves..." + + mkdir -p /opt/pmoves + chown "${SUDO_USER:-$USER}:${SUDO_USER:-$USER}" /opt/pmoves + + # Clone repo if not present + if [ ! -d /opt/pmoves/.git ]; then + log_info "Cloning PMOVES.AI repository..." + git clone --depth 1 https://github.com/POWERFULMOVES/PMOVES.AI.git /opt/pmoves + fi + + # Create node-specific marker + cat > /opt/pmoves/.node-config </dev/null || echo 'not installed')" + log_info "Compose: $(docker compose version 2>/dev/null || echo 'not installed')" + + if command -v tailscale &>/dev/null && tailscale status &>/dev/null; then + log_info "Tailscale IP: $(tailscale ip -4 2>/dev/null || echo 'pending')" + fi + + echo "" + log_info "Next steps:" + case "$NODE_TYPE" in + kvm4-1) + echo " 1. Deploy API services: cd /opt/pmoves/pmoves && docker compose -f docker-compose.yml -f docker-compose.vps.override.yml up -d tensorzero agent-zero hi-rag-gateway-v2 archon-server gateway-agent" + echo " 2. Verify: curl http://localhost:8080/healthz" + ;; + kvm4-2) + echo " 1. Deploy data services: cd /opt/pmoves/pmoves && docker compose -f docker-compose.yml -f docker-compose.vps.override.yml up -d supabase-db supabase-rest qdrant neo4j meilisearch nats prometheus grafana" + echo " 2. Verify: curl http://localhost:9090/api/v1/targets" + ;; + kvm2) + echo " 1. Approve exit node in Tailscale admin: https://login.tailscale.com/admin/machines" + echo " 2. Deploy proxy: cd /opt/pmoves/pmoves && docker compose -f docker-compose.yml -f docker-compose.vps.override.yml up -d nginx" + echo " 3. Use from home: tailscale up --exit-node=pmoves-kvm2" + ;; + esac + echo "" + echo " Runner status: sudo systemctl status github-runner-pmoves-${NODE_TYPE}" + echo " Runner logs: sudo journalctl -u github-runner-pmoves-${NODE_TYPE} -f" +} + +# Main +main() { + validate_node_type + check_env + + log_section "=========================================" + log_section "PMOVES.AI KVM Provisioning: $NODE_TYPE" + log_section "=========================================" + echo "" + + harden_system + install_docker + install_tailscale + install_runner + setup_workdir + show_summary +} + +main "$@" diff --git a/deploy/provision/kvm2-exit-node.sh b/deploy/provision/kvm2-exit-node.sh new file mode 100644 index 0000000000..bdb988bc65 --- /dev/null +++ b/deploy/provision/kvm2-exit-node.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# KVM2 Tailscale Exit Node Configuration +# +# Configures KVM2 as a Tailscale exit node so home machines can route +# traffic through the VPS for faster uploads and lower latency. +# +# Usage: +# TAILSCALE_AUTHKEY=tskey-xxx ./kvm2-exit-node.sh +# +# After running: +# 1. Approve the exit node in Tailscale admin console +# 2. On home machine: tailscale up --exit-node=pmoves-kvm2 + +set -euo pipefail + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +log_info() { echo -e "${GREEN}[INFO]${NC} $1"; } +log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +log_error() { echo -e "${RED}[ERROR]${NC} $1"; } + +# Step 1: Install Tailscale if needed +if ! command -v tailscale &>/dev/null; then + log_info "Installing Tailscale..." + curl -fsSL https://tailscale.com/install.sh | sh +fi + +# Step 2: Enable IP forwarding +log_info "Enabling IP forwarding..." +sysctl -w net.ipv4.ip_forward=1 +sysctl -w net.ipv6.conf.all.forwarding=1 + +# Persist across reboots +cat > /etc/sysctl.d/99-tailscale-exit-node.conf <<'EOF' +# Tailscale exit node — IP forwarding +net.ipv4.ip_forward = 1 +net.ipv6.conf.all.forwarding = 1 +EOF +sysctl --system >/dev/null 2>&1 + +# Step 3: Join Tailscale as exit node +log_info "Configuring Tailscale exit node..." +if [ -n "${TAILSCALE_AUTHKEY:-}" ]; then + tailscale up \ + --auth-key "$TAILSCALE_AUTHKEY" \ + --hostname "pmoves-kvm2" \ + --advertise-exit-node \ + --accept-routes \ + --accept-dns +else + # Already authenticated — just advertise exit node + tailscale set --advertise-exit-node +fi + +# Step 4: Key expiry — tagged auth keys auto-disable expiry. +# For untagged keys, disable manually via Admin Console or Tailscale API: +# POST /api/v2/device/{deviceID}/key {"keyExpiryDisabled": true} +log_info "Key expiry is auto-disabled for tagged auth keys" + +# Step 5: Allow LAN access through exit node +if ! tailscale set --exit-node-allow-lan-access 2>/dev/null; then + log_warn "Could not set --exit-node-allow-lan-access (may require Tailscale 1.22+)" +fi + +# Step 6: Verify +sleep 2 +if tailscale status &>/dev/null; then + ts_ip=$(tailscale ip -4 2>/dev/null || echo "pending") + log_info "Exit node configured successfully" + log_info "Tailscale IP: $ts_ip" + log_info "Hostname: pmoves-kvm2" + echo "" + log_warn "IMPORTANT: Approve exit node in Tailscale admin console:" + echo " https://login.tailscale.com/admin/machines" + echo "" + log_info "Then on home machines, use:" + echo " tailscale up --exit-node=pmoves-kvm2" + echo " tailscale up --exit-node= # to disconnect" +else + log_error "Tailscale not connected. Check authentication." + exit 1 +fi diff --git a/deploy/runners/vps/install-hardened.sh b/deploy/runners/vps/install-hardened.sh index ac85bbddee..dae3162726 100755 --- a/deploy/runners/vps/install-hardened.sh +++ b/deploy/runners/vps/install-hardened.sh @@ -17,16 +17,17 @@ # # Labels applied based on RUNNER_NAME: # cloudstartup: self-hosted, vps, cloudstartup, staging, linux, x64 -# kvm4: self-hosted, vps, kvm4, production, linux, x64 +# kvm4-1: self-hosted, vps, kvm4, kvm4-1, production, linux, x64 +# kvm4-2: self-hosted, vps, kvm4, kvm4-2, production, linux, x64 # kvm2: self-hosted, vps, kvm2, backup, linux, x64 set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" RUNNER_DIR="${RUNNER_DIR:-/opt/actions-runner}" -RUNNER_VERSION="${RUNNER_VERSION:-2.311.0}" +RUNNER_VERSION="${RUNNER_VERSION:-2.321.0}" RUNNER_ARCH="linux-x64" -GITHUB_ORG="${GITHUB_ORG:-frostbytten}" +GITHUB_ORG="${GITHUB_ORG:-POWERFULMOVES}" GITHUB_REPO="${GITHUB_REPO:-PMOVES.AI}" RUNNER_NAME="${RUNNER_NAME:-vps-$(hostname)}" JIT_MODE=false @@ -51,6 +52,12 @@ get_labels() { *cloudstartup*) echo "${base_labels},cloudstartup,staging" ;; + *kvm4-1*) + echo "${base_labels},kvm4,kvm4-1,production" + ;; + *kvm4-2*) + echo "${base_labels},kvm4-2,production" + ;; *kvm4*) echo "${base_labels},kvm4,production" ;; @@ -433,6 +440,12 @@ show_verification() { *cloudstartup*) echo " runs-on: [self-hosted, cloudstartup, staging]" ;; + *kvm4-1*) + echo " runs-on: [self-hosted, vps, kvm4-1, production]" + ;; + *kvm4-2*) + echo " runs-on: [self-hosted, vps, kvm4-2, production]" + ;; *kvm4*) echo " runs-on: [self-hosted, kvm4, production]" ;; diff --git a/deploy/scripts/deploy-vps.sh b/deploy/scripts/deploy-vps.sh new file mode 100644 index 0000000000..b9475a6146 --- /dev/null +++ b/deploy/scripts/deploy-vps.sh @@ -0,0 +1,189 @@ +#!/bin/bash +# PMOVES.AI VPS Fleet Deployment Script +# +# Deploys services to Hostinger KVM nodes via SSH over Tailscale. +# +# Usage: +# ./deploy-vps.sh kvm4-1 # Deploy API gateway services +# ./deploy-vps.sh kvm4-2 # Deploy data services +# ./deploy-vps.sh kvm2 # Deploy exit node + proxy +# ./deploy-vps.sh all # Full fleet deployment +# ./deploy-vps.sh status # Check fleet health +# +# Prerequisites: +# - Tailscale mesh active (all nodes visible in `tailscale status`) +# - SSH keys configured on target nodes +# - Nodes provisioned via deploy/provision/hostinger-kvm-setup.sh + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +# Colors +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +log_info() { echo -e "${GREEN}[INFO]${NC} $1"; } +log_error() { echo -e "${RED}[ERROR]${NC} $1"; } +log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +log_section() { echo -e "${BLUE}[====]${NC} $1"; } + +# Node SSH targets — env-var fallback allows both direct IP (from CHIT secrets) +# and Tailscale hostname discovery +declare -A NODE_SSH +NODE_SSH["kvm4-1"]="${HOSTINGER_KVM4_1_USER:-root}@${HOSTINGER_KVM4_1_IP:-pmoves-kvm4-1}" +NODE_SSH["kvm4-2"]="${HOSTINGER_KVM4_2_USER:-root}@${HOSTINGER_KVM4_2_IP:-pmoves-kvm4-2}" +NODE_SSH["kvm2"]="${HOSTINGER_KVM2_USER:-root}@${HOSTINGER_KVM2_IP:-pmoves-kvm2}" + +# Service groups per node +declare -A NODE_SERVICES +NODE_SERVICES["kvm4-1"]="tensorzero agent-zero hi-rag-gateway-v2 archon-server mesh-agent gateway-agent extract-worker" +NODE_SERVICES["kvm4-2"]="supabase-db supabase-rest qdrant neo4j meilisearch nats prometheus grafana loki minio" +NODE_SERVICES["kvm2"]="nginx" + +COMPOSE_CMD="docker compose -f docker-compose.yml -f docker-compose.vps.override.yml" +WORK_DIR="/opt/pmoves/pmoves" + +# Check Tailscale connectivity to a node +check_node() { + local node="$1" + local ssh_target="${NODE_SSH[$node]}" + + if tailscale ping --timeout 3s "pmoves-${node}" &>/dev/null; then + log_info "$node: Tailscale reachable" + return 0 + else + log_error "$node: Not reachable via Tailscale" + return 1 + fi +} + +# Deploy services to a node +deploy_node() { + local node="$1" + local ssh_target="${NODE_SSH[$node]}" + local services="${NODE_SERVICES[$node]}" + + log_section "Deploying to $node ($ssh_target)..." + + local failed=0 + + # Pull latest code + log_info "$node: Pulling latest code..." + if ! ssh "$ssh_target" "cd /opt/pmoves && git pull --ff-only origin main"; then + log_error "$node: git pull failed — deploying with stale code" + failed=1 + fi + + # Build and start services + log_info "$node: Starting services: $services" + if ! ssh "$ssh_target" "cd ${WORK_DIR} && ${COMPOSE_CMD} pull ${services} 2>/dev/null && ${COMPOSE_CMD} up -d ${services}"; then + log_error "$node: compose pull/up failed" + failed=1 + fi + + # Health check + sleep 5 + log_info "$node: Checking health..." + local health_fail=0 + case "$node" in + kvm4-1) + ssh "$ssh_target" "curl -sf http://localhost:8080/healthz >/dev/null && echo 'Agent Zero: OK' || { echo 'Agent Zero: FAIL'; exit 1; }" || health_fail=1 + ssh "$ssh_target" "curl -sf http://localhost:3030/healthz >/dev/null && echo 'TensorZero: OK' || { echo 'TensorZero: FAIL'; exit 1; }" || health_fail=1 + ssh "$ssh_target" "curl -sf http://localhost:8100/healthz >/dev/null && echo 'Gateway Agent: OK' || { echo 'Gateway Agent: FAIL'; exit 1; }" || health_fail=1 + ;; + kvm4-2) + ssh "$ssh_target" "curl -sf http://localhost:9090/api/v1/targets >/dev/null && echo 'Prometheus: OK' || { echo 'Prometheus: FAIL'; exit 1; }" || health_fail=1 + ssh "$ssh_target" "curl -sf http://localhost:6333/healthz >/dev/null && echo 'Qdrant: OK' || { echo 'Qdrant: FAIL'; exit 1; }" || health_fail=1 + ;; + kvm2) + local kvm2_status + kvm2_status=$(ssh "$ssh_target" "docker compose -f docker-compose.yml -f docker-compose.vps.override.yml ps nginx --format '{{.Status}}'" 2>/dev/null) + if echo "$kvm2_status" | grep -qi "Up"; then + echo "nginx: $kvm2_status" + else + log_error "kvm2: nginx not running (status: ${kvm2_status:-empty})" + health_fail=1 + fi + ;; + esac + + if [ "$health_fail" -ne 0 ]; then + log_error "$node: One or more health checks failed" + failed=1 + fi + + if [ "$failed" -ne 0 ]; then + log_warn "$node: Deployment completed with errors" + return 1 + fi + log_info "$node: Deployment complete" +} + +# Show fleet status +fleet_status() { + log_section "PMOVES.AI VPS Fleet Status" + echo "" + + for node in kvm4-1 kvm4-2 kvm2; do + local ssh_target="${NODE_SSH[$node]}" + + echo -n " $node: " + if tailscale ping --timeout 3s "pmoves-${node}" &>/dev/null 2>&1; then + echo -e "${GREEN}ONLINE${NC}" + ssh "$ssh_target" "cd ${WORK_DIR} && ${COMPOSE_CMD} ps --format 'table {{.Name}}\t{{.Status}}' 2>/dev/null" | sed 's/^/ /' + else + echo -e "${RED}OFFLINE${NC}" + fi + echo "" + done + + # Runner status + log_section "GitHub Actions Runner Status" + if command -v gh &>/dev/null; then + gh api repos/POWERFULMOVES/PMOVES.AI/actions/runners --jq '.runners[] | " \(.name): \(.status) [\(.labels | map(.name) | join(", "))]"' 2>/dev/null || echo " (unable to fetch runner status)" + fi +} + +# Main +case "${1:-}" in + kvm4-1|kvm4-2|kvm2) + check_node "$1" && deploy_node "$1" + ;; + all) + log_section "Full fleet deployment" + deploy_failures=0 + for node in kvm4-2 kvm4-1 kvm2; do + # Deploy data first, then API, then proxy + if check_node "$node"; then + deploy_node "$node" || deploy_failures=$((deploy_failures + 1)) + else + deploy_failures=$((deploy_failures + 1)) + fi + echo "" + done + fleet_status + if [ "$deploy_failures" -gt 0 ]; then + log_error "$deploy_failures node(s) had deployment failures" + exit 1 + fi + ;; + status) + fleet_status + ;; + *) + echo "Usage: $0 " + echo "" + echo "Nodes:" + echo " kvm4-1 API Gateway (TensorZero, Agent Zero, Hi-RAG, Archon)" + echo " kvm4-2 Data Services (Supabase, Qdrant, Neo4j, Meilisearch, NATS)" + echo " kvm2 Exit Node (Nginx reverse proxy, SSL termination)" + echo " all Deploy entire fleet (data → API → proxy order)" + echo " status Show fleet health and runner status" + exit 1 + ;; +esac diff --git a/pbnj/pinokio/api/pmoves-pbnj/kvm2-deploy.json b/pbnj/pinokio/api/pmoves-pbnj/kvm2-deploy.json new file mode 100644 index 0000000000..863d711886 --- /dev/null +++ b/pbnj/pinokio/api/pmoves-pbnj/kvm2-deploy.json @@ -0,0 +1,17 @@ +{ + "run": [ + { + "method": "shell.run", + "params": { + "message": [ + "echo 'Deploying KVM2 (Exit Node) via Tailscale SSH...'", + "echo 'NOTE: SSH as root — key-only auth enforced (PasswordAuthentication no)'", + "ssh root@pmoves-kvm2 'cd /opt/pmoves && git pull --ff-only origin main && cd pmoves && docker compose -f docker-compose.yml -f docker-compose.vps.override.yml pull nginx && docker compose -f docker-compose.yml -f docker-compose.vps.override.yml up -d nginx'", + "echo 'Verifying exit node...'", + "ssh root@pmoves-kvm2 'tailscale status | head -5'", + "echo 'KVM2 deployment complete.'" + ] + } + } + ] +} diff --git a/pbnj/pinokio/api/pmoves-pbnj/kvm4-1-deploy.json b/pbnj/pinokio/api/pmoves-pbnj/kvm4-1-deploy.json new file mode 100644 index 0000000000..bab4b8990a --- /dev/null +++ b/pbnj/pinokio/api/pmoves-pbnj/kvm4-1-deploy.json @@ -0,0 +1,18 @@ +{ + "run": [ + { + "method": "shell.run", + "params": { + "message": [ + "echo 'Deploying KVM4-1 (API Gateway) via Tailscale SSH...'", + "echo 'NOTE: SSH as root — key-only auth enforced (PasswordAuthentication no)'", + "ssh root@pmoves-kvm4-1 'cd /opt/pmoves && git pull --ff-only origin main && cd pmoves && docker compose -f docker-compose.yml -f docker-compose.vps.override.yml pull tensorzero-gateway agent-zero hi-rag-gateway-v2 archon-server mesh-agent gateway-agent extract-worker && docker compose -f docker-compose.yml -f docker-compose.vps.override.yml up -d tensorzero-gateway agent-zero hi-rag-gateway-v2 archon-server mesh-agent gateway-agent extract-worker'", + "echo 'Verifying health...'", + "ssh root@pmoves-kvm4-1 'curl -sf http://localhost:8080/healthz && echo \" Agent Zero: OK\" || echo \" Agent Zero: FAIL\"'", + "ssh root@pmoves-kvm4-1 'curl -sf http://localhost:3030/healthz && echo \" TensorZero: OK\" || echo \" TensorZero: FAIL\"'", + "echo 'KVM4-1 deployment complete.'" + ] + } + } + ] +} diff --git a/pbnj/pinokio/api/pmoves-pbnj/kvm4-2-deploy.json b/pbnj/pinokio/api/pmoves-pbnj/kvm4-2-deploy.json new file mode 100644 index 0000000000..251d23dba1 --- /dev/null +++ b/pbnj/pinokio/api/pmoves-pbnj/kvm4-2-deploy.json @@ -0,0 +1,18 @@ +{ + "run": [ + { + "method": "shell.run", + "params": { + "message": [ + "echo 'Deploying KVM4-2 (Data Services) via Tailscale SSH...'", + "echo 'NOTE: SSH as root — key-only auth enforced (PasswordAuthentication no)'", + "ssh root@pmoves-kvm4-2 'cd /opt/pmoves && git pull --ff-only origin main && cd pmoves && docker compose -f docker-compose.yml -f docker-compose.vps.override.yml pull supabase-db supabase-rest qdrant neo4j meilisearch nats prometheus grafana loki minio && docker compose -f docker-compose.yml -f docker-compose.vps.override.yml up -d supabase-db supabase-rest qdrant neo4j meilisearch nats prometheus grafana loki minio'", + "echo 'Verifying health...'", + "ssh root@pmoves-kvm4-2 'curl -sf http://localhost:9090/api/v1/targets > /dev/null && echo \" Prometheus: OK\" || echo \" Prometheus: FAIL\"'", + "ssh root@pmoves-kvm4-2 'curl -sf http://localhost:6333/healthz > /dev/null && echo \" Qdrant: OK\" || echo \" Qdrant: FAIL\"'", + "echo 'KVM4-2 deployment complete.'" + ] + } + } + ] +} diff --git a/pbnj/pinokio/api/pmoves-pbnj/pinokio.js b/pbnj/pinokio/api/pmoves-pbnj/pinokio.js index 44694c17da..9561a920cb 100644 --- a/pbnj/pinokio/api/pmoves-pbnj/pinokio.js +++ b/pbnj/pinokio/api/pmoves-pbnj/pinokio.js @@ -14,6 +14,12 @@ module.exports = { { text: "Local Dev (Docker) - Down",href: "local-down.json" }, { text: "Local Dev (Docker) Logs", href: "local-logs.json" }, - { text: "Cluster Status (AI Lab)", href: "status.json" } + { text: "Cluster Status (AI Lab)", href: "status.json" }, + + { text: "─── VPS Fleet ───", href: "" }, + { text: "Deploy KVM4-1 (API Gateway)", href: "kvm4-1-deploy.json" }, + { text: "Deploy KVM4-2 (Data Services)",href: "kvm4-2-deploy.json" }, + { text: "Deploy KVM2 (Exit Node)", href: "kvm2-deploy.json" }, + { text: "VPS Fleet Status", href: "vps-status.json" } ] }; diff --git a/pbnj/pinokio/api/pmoves-pbnj/vps-status.json b/pbnj/pinokio/api/pmoves-pbnj/vps-status.json new file mode 100644 index 0000000000..b00141872b --- /dev/null +++ b/pbnj/pinokio/api/pmoves-pbnj/vps-status.json @@ -0,0 +1,27 @@ +{ + "run": [ + { + "method": "shell.run", + "params": { + "message": [ + "echo '=== PMOVES.AI VPS Fleet Status ==='", + "echo ''", + "echo 'KVM4-1 (API Gateway):'", + "tailscale ping --timeout 3s pmoves-kvm4-1 > /dev/null 2>&1 && echo ' Status: ONLINE' || echo ' Status: OFFLINE'", + "echo ''", + "echo 'KVM4-2 (Data Services):'", + "tailscale ping --timeout 3s pmoves-kvm4-2 > /dev/null 2>&1 && echo ' Status: ONLINE' || echo ' Status: OFFLINE'", + "echo ''", + "echo 'KVM2 (Exit Node):'", + "tailscale ping --timeout 3s pmoves-kvm2 > /dev/null 2>&1 && echo ' Status: ONLINE' || echo ' Status: OFFLINE'", + "echo ''", + "echo 'GitHub Actions Runners:'", + "gh api repos/POWERFULMOVES/PMOVES.AI/actions/runners --jq '.runners[] | \" \\(.name): \\(.status)\"' 2>/dev/null || echo ' (unable to fetch)'", + "echo ''", + "echo 'Tailscale Mesh:'", + "tailscale status 2>/dev/null | head -10 || echo ' Tailscale not connected'" + ] + } + } + ] +} diff --git a/pmoves/Makefile b/pmoves/Makefile index e5a198c1c4..84a2484d64 100644 --- a/pmoves/Makefile +++ b/pmoves/Makefile @@ -250,7 +250,7 @@ SUPABASE_DB_HELPER ?= scripts/supabase/find_db_container.sh up-supabase: ## Start Supabase using selected runtime (SUPABASE_RUNTIME=cli|kong|compose) @$(MAKE) --no-print-directory supa-start -.PHONY: supa-init supa-start supa-stop supa-stop-all supa-status supa-runtime-env supa-logs supa-health supa-restart supa-migrate supa-use-local supa-use-remote supa-env-doctor supa-env-doctor-strict supa-runtime-guard supa-runtime-reconcile +.PHONY: supa-init supa-start supa-stop supa-stop-all supa-status supa-runtime-env supa-logs supa-health supa-restart supa-migrate supa-use-local supa-use-remote supa-env-doctor supa-env-doctor-strict supa-runtime-guard supa-runtime-reconcile supa-collation-refresh supa-collation-check supa-init: check-tools ## Initialize supabase/config.toml (one-time) and enforce PMOVES CLI defaults @if [ ! -f "$(SUPABASE_CONFIG)" ]; then \ echo "🗂️ Initializing Supabase project in . ..."; \ @@ -313,6 +313,7 @@ supa-start: check-tools ensure-env-shared ## Start Supabase stack for selected r $(DC) up -d supabase-postgrest supabase-gotrue supabase-kong supabase-realtime supabase-storage supabase-studio; \ fi @$(MAKE) --no-print-directory supa-status + @$(MAKE) --no-print-directory supa-collation-refresh 2>/dev/null || true supa-stop: ## Stop Supabase stack for selected runtime @echo "🗄️ Stopping Supabase stack (SUPABASE_RUNTIME=$(SUPABASE_RUNTIME))..." @@ -461,6 +462,24 @@ supa-health: ## Health checks for selected runtime + active DB container readine echo " ❌ Studio ($$studio_url) -> $$studio_code"; \ fi +supa-collation-refresh: ## Refresh collation version for all Supabase databases (RG-3) + @echo "Refreshing collation versions..." + @db=$$(bash "$(SUPABASE_DB_HELPER)" running); \ + if [ -z "$$db" ]; then echo "Supabase DB container not found"; exit 1; fi; \ + for dbname in postgres _supabase; do \ + echo " -> ALTER DATABASE $$dbname REFRESH COLLATION VERSION"; \ + docker exec -i "$$db" psql -U postgres -d "$$dbname" \ + -c "ALTER DATABASE $$dbname REFRESH COLLATION VERSION;" 2>&1 || true; \ + done + @echo "Collation refresh complete" + +supa-collation-check: ## Check for collation version mismatches + @db=$$(bash "$(SUPABASE_DB_HELPER)" running); \ + if [ -z "$$db" ]; then echo "Supabase DB container not found"; exit 1; fi; \ + docker exec -i "$$db" psql -U postgres -tAc \ + "SELECT datname || ': ' || COALESCE(datcollversion, 'NULL') FROM pg_database WHERE datname NOT IN ('template0','template1') ORDER BY datname;" + @echo "Collation check complete" + supa-use-local: ## Write .env.local from local Supabase template and merge keys from current supa-status @$(PYTHON) scripts/supabase/apply_env_profile.py --profile local --runtime "$(SUPABASE_RUNTIME)" --target .env.local --status-file .supabase.status.env @echo "✅ .env.local updated for SUPABASE_RUNTIME=$(SUPABASE_RUNTIME)" diff --git a/pmoves/chit/secrets_manifest.yaml b/pmoves/chit/secrets_manifest.yaml index 58bb99057d..fa6ac730a0 100644 --- a/pmoves/chit/secrets_manifest.yaml +++ b/pmoves/chit/secrets_manifest.yaml @@ -874,12 +874,74 @@ entries: source: type: cgp label: HOSTINGER_API_TOKEN + aliases: + - HOSTINGER_API_KEY targets: - file: .env.generated key: HOSTINGER_API_TOKEN - file: env.tier-agent key: HOSTINGER_API_TOKEN required: false +- id: hostinger_kvm4_1_ip + source: + type: cgp + label: HOSTINGER_KVM4_1_IP + targets: + - file: .env.generated + key: HOSTINGER_KVM4_1_IP + - file: env.tier-agent + key: HOSTINGER_KVM4_1_IP + required: false +- id: hostinger_kvm4_1_user + source: + type: cgp + label: HOSTINGER_KVM4_1_USER + targets: + - file: .env.generated + key: HOSTINGER_KVM4_1_USER + - file: env.tier-agent + key: HOSTINGER_KVM4_1_USER + required: false +- id: hostinger_kvm4_2_ip + source: + type: cgp + label: HOSTINGER_KVM4_2_IP + targets: + - file: .env.generated + key: HOSTINGER_KVM4_2_IP + - file: env.tier-agent + key: HOSTINGER_KVM4_2_IP + required: false +- id: hostinger_kvm4_2_user + source: + type: cgp + label: HOSTINGER_KVM4_2_USER + targets: + - file: .env.generated + key: HOSTINGER_KVM4_2_USER + - file: env.tier-agent + key: HOSTINGER_KVM4_2_USER + required: false +- id: hostinger_kvm2_ip + source: + type: cgp + label: HOSTINGER_KVM2_IP + targets: + - file: .env.generated + key: HOSTINGER_KVM2_IP + - file: env.tier-agent + key: HOSTINGER_KVM2_IP + required: false +- id: hostinger_kvm2_user + source: + type: cgp + label: HOSTINGER_KVM2_USER + targets: + - file: .env.generated + key: HOSTINGER_KVM2_USER + - file: env.tier-agent + key: HOSTINGER_KVM2_USER + required: false - id: hostinger_ssh_private_key source: type: cgp diff --git a/pmoves/chit/secrets_manifest_v2.yaml b/pmoves/chit/secrets_manifest_v2.yaml index 8d0961825f..5fecb4b705 100644 --- a/pmoves/chit/secrets_manifest_v2.yaml +++ b/pmoves/chit/secrets_manifest_v2.yaml @@ -1096,6 +1096,8 @@ entries: source: type: cgp label: HOSTINGER_API_TOKEN + aliases: + - HOSTINGER_API_KEY targets: - file: .env.generated key: HOSTINGER_API_TOKEN @@ -1105,6 +1107,84 @@ entries: - docker_secret: pmoves_hostinger_api_token required: false tier: agent +- id: hostinger_kvm4_1_ip + source: + type: cgp + label: HOSTINGER_KVM4_1_IP + targets: + - file: .env.generated + key: HOSTINGER_KVM4_1_IP + - file: env.tier-agent + key: HOSTINGER_KVM4_1_IP + - github_secret: HOSTINGER_KVM4_1_IP + - docker_secret: pmoves_hostinger_kvm4_1_ip + required: false + tier: agent +- id: hostinger_kvm4_1_user + source: + type: cgp + label: HOSTINGER_KVM4_1_USER + targets: + - file: .env.generated + key: HOSTINGER_KVM4_1_USER + - file: env.tier-agent + key: HOSTINGER_KVM4_1_USER + - github_secret: HOSTINGER_KVM4_1_USER + - docker_secret: pmoves_hostinger_kvm4_1_user + required: false + tier: agent +- id: hostinger_kvm4_2_ip + source: + type: cgp + label: HOSTINGER_KVM4_2_IP + targets: + - file: .env.generated + key: HOSTINGER_KVM4_2_IP + - file: env.tier-agent + key: HOSTINGER_KVM4_2_IP + - github_secret: HOSTINGER_KVM4_2_IP + - docker_secret: pmoves_hostinger_kvm4_2_ip + required: false + tier: agent +- id: hostinger_kvm4_2_user + source: + type: cgp + label: HOSTINGER_KVM4_2_USER + targets: + - file: .env.generated + key: HOSTINGER_KVM4_2_USER + - file: env.tier-agent + key: HOSTINGER_KVM4_2_USER + - github_secret: HOSTINGER_KVM4_2_USER + - docker_secret: pmoves_hostinger_kvm4_2_user + required: false + tier: agent +- id: hostinger_kvm2_ip + source: + type: cgp + label: HOSTINGER_KVM2_IP + targets: + - file: .env.generated + key: HOSTINGER_KVM2_IP + - file: env.tier-agent + key: HOSTINGER_KVM2_IP + - github_secret: HOSTINGER_KVM2_IP + - docker_secret: pmoves_hostinger_kvm2_ip + required: false + tier: agent +- id: hostinger_kvm2_user + source: + type: cgp + label: HOSTINGER_KVM2_USER + targets: + - file: .env.generated + key: HOSTINGER_KVM2_USER + - file: env.tier-agent + key: HOSTINGER_KVM2_USER + - github_secret: HOSTINGER_KVM2_USER + - docker_secret: pmoves_hostinger_kvm2_user + required: false + tier: agent - id: hostinger_ssh_private_key source: type: cgp diff --git a/pmoves/config/agent_registry.yaml b/pmoves/config/agent_registry.yaml index 295cbd7e62..67d8c73b91 100644 --- a/pmoves/config/agent_registry.yaml +++ b/pmoves/config/agent_registry.yaml @@ -684,6 +684,30 @@ agents: submodule: "Pmoves-hyperdimensions" description: "Geometry visualization surface and control plane (L2.5)" + vps_fleet_manager: + name: "VPS Fleet Manager" + class: utility + primary_type: api + secondary_type: agent + port: null + health: null + layers: [L0, L2] + evolution_stage: base + nats: + publishes: ["mesh.vps.deploy.v1", "mesh.vps.status.v1"] + subscribes: ["mesh.vps.command.v1"] + chit_toggles: + delta_sensitive: false + kappa_sensitive: false + hz_sensitive: false + swarm_participant: false + attribution_gated: false + resilience: + context_budget: small + checkpoint_frequency: per_wave + recovery_strategy: manual_handoff + description: "Hostinger KVM fleet orchestration — deploy, status, restart via MCP tools" + # --- Data infrastructure (Utility class) --- nats: diff --git a/pmoves/docker-compose.vps.override.yml b/pmoves/docker-compose.vps.override.yml index 2d72aa07a9..83e84cecde 100644 --- a/pmoves/docker-compose.vps.override.yml +++ b/pmoves/docker-compose.vps.override.yml @@ -31,8 +31,8 @@ services: tensorzero: <<: [*cpu-only, *vps-healthcheck] environment: - # Route GPU-intensive requests to home network via WireGuard - - OLLAMA_BASE_URL=${HOME_OLLAMA_URL:-http://10.0.0.1:11434} + # Route GPU-intensive requests to home network via Tailscale mesh + - OLLAMA_BASE_URL=${HOME_OLLAMA_URL:-http://pmoves-home:11434} - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - GEMINI_API_KEY=${GEMINI_API_KEY} # Default to cloud models on VPS @@ -44,7 +44,7 @@ services: dockerfile: Dockerfile # CPU-only version environment: - AGENTZERO_MODE=api - - TENSORZERO_URL=http://tensorzero:3030 + - TENSORZERO_URL=http://tensorzero:3000 hi-rag-gateway-v2: <<: [*cpu-only, *vps-healthcheck] @@ -75,7 +75,7 @@ services: - PORT=8100 - AGENT_ZERO_URL=http://agent-zero:8080 - CIPHER_URL=http://pmoves-botz-cipher:8000 - - TENSORZERO_URL=http://tensorzero-gateway:3000 + - TENSORZERO_URL=http://tensorzero:3000 - SUPABASE_URL=${SUPABASE_URL:-http://supabase-rest:3010} - SUPABASE_SERVICE_KEY=${SUPABASE_SERVICE_KEY} - TOOL_CACHE_TTL=300 @@ -168,25 +168,6 @@ services: timeout: 5s retries: 3 - # WireGuard for home network tunnel - wireguard: - image: linuxserver/wireguard - cap_add: - - NET_ADMIN - - SYS_MODULE - environment: - - PUID=1000 - - PGID=1000 - volumes: - - ./wireguard:/config - - /lib/modules:/lib/modules:ro - sysctls: - - net.ipv4.conf.all.src_valid_mark=1 - deploy: - resources: - limits: - cpus: '0.5' - memory: 256M # ============================================================================ # GPU Services - DISABLED on VPS @@ -235,11 +216,6 @@ volumes: networks: pmoves-net: driver: bridge - wireguard-net: - driver: bridge - ipam: - config: - - subnet: 10.0.0.0/24 # API Tier network (same name as base docker-compose.yml) pmoves_api: name: pmoves_api diff --git a/pmoves/docs/AGENTS/TOOLING_SCRIPT_AUDIT.md b/pmoves/docs/AGENTS/TOOLING_SCRIPT_AUDIT.md index 0f8306a107..266c32a038 100644 --- a/pmoves/docs/AGENTS/TOOLING_SCRIPT_AUDIT.md +++ b/pmoves/docs/AGENTS/TOOLING_SCRIPT_AUDIT.md @@ -1,11 +1,11 @@ # PMOVES Tooling Overlay Audit -_Generated: 2026-03-02_ +_Generated: 2026-03-08_ ## Summary -- PMOVES scripts/tools scanned: **212** -- PMOVES auth/user/login-focused entries: **34** -- Submodule keyword-matched scripts/tools: **119** -- Potential overlap rows: **117** +- PMOVES scripts/tools scanned: **219** +- PMOVES auth/user/login-focused entries: **35** +- Submodule keyword-matched scripts/tools: **178** +- Potential overlap rows: **124** - Keywords with overlap: **auth, bootstrap, credential, profile, secret, token, user** - Findings: **0 error(s)**, **0 warning(s)** @@ -26,6 +26,10 @@ _Generated: 2026-03-02_ ## Overlap Candidates | Keyword | Score | PMOVES Script/Tool | Submodule | Submodule Script/Tool | Shared Tokens | | --- | --- | --- | --- | --- | --- | +| `auth` | 0.57 | `pmoves/tools/auth_bootstrap_check.py` | `PMOVES-transcribe-and-fetch` | `PMOVES-transcribe-and-fetch/pmoves-integrations/auth/bootstrap.py` | auth, bootstrap, pmoves, py | +| `auth` | 0.38 | `pmoves/scripts/integration-auth-setup.sh` | `PMOVES-transcribe-and-fetch` | `PMOVES-transcribe-and-fetch/pmoves-integrations/auth/bootstrap.sh` | auth, pmoves, sh | +| `auth` | 0.38 | `pmoves/tools/auth_alignment_check.py` | `PMOVES-transcribe-and-fetch` | `PMOVES-transcribe-and-fetch/pmoves-integrations/auth/bootstrap.py` | auth, pmoves, py | +| `auth` | 0.38 | `pmoves/tools/auth_bootstrap_check.py` | `PMOVES-transcribe-and-fetch` | `PMOVES-transcribe-and-fetch/pmoves-integrations/auth/bootstrap.sh` | auth, bootstrap, pmoves | | `auth` | 0.33 | `pmoves/tools/auth_alignment_check.py` | `PMOVES-Open-Notebook` | `PMOVES-Open-Notebook/api/auth.py` | auth, pmoves, py | | `auth` | 0.33 | `pmoves/tools/auth_bootstrap_check.py` | `PMOVES-Open-Notebook` | `PMOVES-Open-Notebook/api/auth.py` | auth, pmoves, py | | `auth` | 0.25 | `pmoves/tools/auth_alignment_check.py` | `PMOVES-transcribe-and-fetch` | `PMOVES-transcribe-and-fetch/pmoves-ottomator-agents/tweet-generator-agent/twitter_auth.py` | auth, pmoves, py | @@ -33,6 +37,7 @@ _Generated: 2026-03-02_ | `auth` | 0.25 | `pmoves/tools/auth_bootstrap_check.py` | `PMOVES-transcribe-and-fetch` | `PMOVES-transcribe-and-fetch/pmoves-ottomator-agents/tweet-generator-agent/twitter_auth.py` | auth, pmoves, py | | `auth` | 0.25 | `pmoves/tools/auth_bootstrap_check.py` | `PMOVES-Open-Notebook` | `PMOVES-Open-Notebook/api/routers/auth.py` | auth, py | | `auth` | 0.22 | `pmoves/scripts/integration-auth-setup.sh` | `Pmoves-hyperdimensions` | `Pmoves-hyperdimensions/portal/portal-auth.js` | auth, pmoves | +| `auth` | 0.22 | `pmoves/scripts/integration-auth-setup.sh` | `PMOVES-transcribe-and-fetch` | `PMOVES-transcribe-and-fetch/pmoves-integrations/auth/bootstrap.py` | auth, pmoves | | `auth` | 0.22 | `pmoves/scripts/integration-auth-setup.sh` | `PMOVES-DoX` | `PMOVES-DoX/external/PMOVES-supabase/scripts/authorizeVercelDeploys.ts` | pmoves, scripts | | `auth` | 0.22 | `pmoves/scripts/integration-auth-setup.sh` | `PMOVES-Tailscale` | `PMOVES-Tailscale/cmd/nginx-auth/mkdeb.sh` | auth, sh | | `auth` | 0.22 | `pmoves/scripts/integration-auth-setup.sh` | `PMOVES-Tailscale` | `PMOVES-Tailscale/cmd/nginx-auth/deb/postinst.sh` | auth, sh | @@ -41,11 +46,6 @@ _Generated: 2026-03-02_ | `auth` | 0.22 | `pmoves/scripts/integration-auth-setup.sh` | `PMOVES-Tailscale` | `PMOVES-Tailscale/cmd/nginx-auth/rpm/postinst.sh` | auth, sh | | `auth` | 0.22 | `pmoves/scripts/integration-auth-setup.sh` | `PMOVES-Tailscale` | `PMOVES-Tailscale/cmd/nginx-auth/rpm/postrm.sh` | auth, sh | | `auth` | 0.22 | `pmoves/scripts/integration-auth-setup.sh` | `PMOVES-Tailscale` | `PMOVES-Tailscale/cmd/nginx-auth/rpm/prerm.sh` | auth, sh | -| `auth` | 0.22 | `pmoves/scripts/integration-auth-setup.sh` | `PMOVES-supabase` | `PMOVES-supabase/scripts/authorizeVercelDeploys.ts` | pmoves, scripts | -| `auth` | 0.22 | `pmoves/tools/auth_alignment_check.py` | `PMOVES-BoTZ` | `PMOVES-BoTZ/features/mcp_bridge/auth.py` | auth, py | -| `auth` | 0.22 | `pmoves/tools/auth_alignment_check.py` | `Pmoves-hyperdimensions` | `Pmoves-hyperdimensions/portal/portal-auth.js` | auth, pmoves | -| `auth` | 0.22 | `pmoves/tools/auth_bootstrap_check.py` | `PMOVES-BoTZ` | `PMOVES-BoTZ/features/mcp_bridge/auth.py` | auth, py | -| `auth` | 0.22 | `pmoves/tools/auth_bootstrap_check.py` | `Pmoves-hyperdimensions` | `Pmoves-hyperdimensions/portal/portal-auth.js` | auth, pmoves | | `bootstrap` | 0.57 | `pmoves/scripts/bootstrap_env.py` | `PMOVES-Archon` | `PMOVES-Archon/external/PMOVES-BoTZ/scripts/bootstrap_env.ps1` | bootstrap, env, pmoves, scripts | | `bootstrap` | 0.57 | `pmoves/scripts/bootstrap_env.py` | `PMOVES-BoTZ` | `PMOVES-BoTZ/scripts/bootstrap_env.ps1` | bootstrap, env, pmoves, scripts | | `bootstrap` | 0.57 | `pmoves/scripts/bootstrap_env.py` | `PMOVES-DoX` | `PMOVES-DoX/scripts/bootstrap_env.ps1` | bootstrap, env, pmoves, scripts | @@ -62,10 +62,10 @@ _Generated: 2026-03-02_ | `bootstrap` | 0.57 | `pmoves/scripts/windows_bootstrap.ps1` | `PMOVES-BoTZ` | `PMOVES-BoTZ/scripts/bootstrap_env.ps1` | bootstrap, pmoves, ps1, scripts | | `bootstrap` | 0.57 | `pmoves/scripts/windows_bootstrap.ps1` | `PMOVES-DoX` | `PMOVES-DoX/scripts/bootstrap_env.ps1` | bootstrap, pmoves, ps1, scripts | | `bootstrap` | 0.57 | `pmoves/scripts/windows_bootstrap.ps1` | `pmoves/integrations/archon` | `pmoves/integrations/archon/external/PMOVES-BoTZ/scripts/bootstrap_env.ps1` | bootstrap, pmoves, ps1, scripts | +| `bootstrap` | 0.57 | `pmoves/tools/auth_bootstrap_check.py` | `PMOVES-transcribe-and-fetch` | `PMOVES-transcribe-and-fetch/pmoves-integrations/auth/bootstrap.py` | auth, bootstrap, pmoves, py | | `bootstrap` | 0.50 | `pmoves/scripts/codex_bootstrap.ps1` | `PMOVES-Agent-Zero` | `PMOVES-Agent-Zero/scripts/bootstrap_credentials.ps1` | bootstrap, pmoves, ps1, scripts | | `bootstrap` | 0.50 | `pmoves/scripts/codex_bootstrap.ps1` | `PMOVES-Archon` | `PMOVES-Archon/external/PMOVES-Agent-Zero/scripts/bootstrap_credentials.ps1` | bootstrap, pmoves, ps1, scripts | | `bootstrap` | 0.50 | `pmoves/scripts/codex_bootstrap.ps1` | `PMOVES-DoX` | `PMOVES-DoX/external/PMOVES-Agent-Zero/scripts/bootstrap_credentials.ps1` | bootstrap, pmoves, ps1, scripts | -| `bootstrap` | 0.50 | `pmoves/scripts/codex_bootstrap.ps1` | `pmoves/integrations/archon` | `pmoves/integrations/archon/external/PMOVES-Agent-Zero/scripts/bootstrap_credentials.ps1` | bootstrap, pmoves, ps1, scripts | | `credential` | 0.50 | `pmoves/scripts/fetch_credentials.sh` | `PMOVES-Agent-Zero` | `PMOVES-Agent-Zero/scripts/bootstrap_credentials.sh` | credentials, pmoves, scripts, sh | | `credential` | 0.50 | `pmoves/scripts/fetch_credentials.sh` | `PMOVES-Archon` | `PMOVES-Archon/external/PMOVES-Agent-Zero/scripts/bootstrap_credentials.sh` | credentials, pmoves, scripts, sh | | `credential` | 0.50 | `pmoves/scripts/fetch_credentials.sh` | `PMOVES-DoX` | `PMOVES-DoX/external/PMOVES-Agent-Zero/scripts/bootstrap_credentials.sh` | credentials, pmoves, scripts, sh | @@ -82,10 +82,10 @@ _Generated: 2026-03-02_ | `credential` | 0.33 | `pmoves/scripts/fetch_credentials.sh` | `PMOVES-Archon` | `PMOVES-Archon/external/PMOVES-Agent-Zero/scripts/bootstrap_credentials.ps1` | credentials, pmoves, scripts | | `credential` | 0.33 | `pmoves/scripts/fetch_credentials.sh` | `PMOVES-DoX` | `PMOVES-DoX/external/PMOVES-Agent-Zero/scripts/bootstrap_credentials.ps1` | credentials, pmoves, scripts | | `credential` | 0.33 | `pmoves/scripts/fetch_credentials.sh` | `pmoves/integrations/archon` | `pmoves/integrations/archon/external/PMOVES-Agent-Zero/scripts/bootstrap_credentials.ps1` | credentials, pmoves, scripts | -| `credential` | 0.22 | `pmoves/scripts/credentials/print_credentials.ps1` | `PMOVES-Agent-Zero` | `PMOVES-Agent-Zero/scripts/bootstrap_credentials.sh` | credentials, scripts | -| `credential` | 0.22 | `pmoves/scripts/credentials/print_credentials.ps1` | `PMOVES-Archon` | `PMOVES-Archon/external/PMOVES-Agent-Zero/scripts/bootstrap_credentials.sh` | credentials, scripts | -| `credential` | 0.22 | `pmoves/scripts/credentials/print_credentials.ps1` | `PMOVES-DoX` | `PMOVES-DoX/external/PMOVES-Agent-Zero/scripts/bootstrap_credentials.sh` | credentials, scripts | -| `credential` | 0.22 | `pmoves/scripts/credentials/print_credentials.ps1` | `pmoves/integrations/archon` | `pmoves/integrations/archon/external/PMOVES-Agent-Zero/scripts/bootstrap_credentials.sh` | credentials, scripts | +| `credential` | 0.25 | `pmoves/scripts/credentials/set_archon_provider.py` | `PMOVES-Open-Notebook` | `PMOVES-Open-Notebook/api/routers/credentials.py` | credentials, py | +| `credential` | 0.25 | `pmoves/tools/credential_fetcher.py` | `PMOVES-Open-Notebook` | `PMOVES-Open-Notebook/open_notebook/domain/credential.py` | credential, py | +| `credential` | 0.25 | `pmoves/tools/credential_setup.py` | `PMOVES-Open-Notebook` | `PMOVES-Open-Notebook/open_notebook/domain/credential.py` | credential, py | +| `credential` | 0.25 | `pmoves/tools/credential_urlencoder.py` | `PMOVES-Open-Notebook` | `PMOVES-Open-Notebook/open_notebook/domain/credential.py` | credential, py | | `profile` | 0.18 | `pmoves/tools/profile_loader.py` | `PMOVES-Open-Notebook` | `PMOVES-Open-Notebook/api/episode_profiles_service.py` | pmoves, py | | `profile` | 0.11 | `pmoves/tools/profile_loader.py` | `PMOVES.YT` | `PMOVES.YT/yt_dlp/extractor/eroprofile.py` | py | | `profile` | 0.11 | `pmoves/tools/profile_loader.py` | `PMOVES-Open-Notebook` | `PMOVES-Open-Notebook/api/routers/episode_profiles.py` | py | @@ -114,11 +114,16 @@ _Generated: 2026-03-02_ | `secret` | 0.17 | `pmoves/tools/check_required_secrets.py` | `PMOVES-Archon` | `PMOVES-Archon/external/PMOVES-Agent-Zero/python/extensions/tool_execute_before/_10_unmask_secrets.py` | py, secrets | | `secret` | 0.17 | `pmoves/tools/check_required_secrets.py` | `PMOVES-DoX` | `PMOVES-DoX/external/PMOVES-Agent-Zero/python/extensions/tool_execute_after/_10_mask_secrets.py` | py, secrets | | `secret` | 0.17 | `pmoves/tools/check_required_secrets.py` | `PMOVES-DoX` | `PMOVES-DoX/external/PMOVES-Agent-Zero/python/extensions/tool_execute_before/_10_unmask_secrets.py` | py, secrets | +| `token` | 0.22 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-Archon` | `PMOVES-Archon/python/.venv/Lib/site-packages/tokenizers/tools/visualizer.py` | py, tools | +| `token` | 0.22 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-Archon` | `PMOVES-Archon/python/.venv/Lib/site-packages/tokenizers/tools/__init__.py` | py, tools | | `token` | 0.22 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-Pipecat` | `PMOVES-Pipecat/.venv/Lib/site-packages/tokenizers/tools/visualizer.py` | py, tools | | `token` | 0.22 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-Pipecat` | `PMOVES-Pipecat/.venv/Lib/site-packages/tokenizers/tools/__init__.py` | py, tools | +| `token` | 0.22 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-Open-Notebook` | `PMOVES-Open-Notebook/.venv/Lib/site-packages/tokenizers/tools/visualizer.py` | py, tools | +| `token` | 0.22 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-Open-Notebook` | `PMOVES-Open-Notebook/.venv/Lib/site-packages/tokenizers/tools/__init__.py` | py, tools | | `token` | 0.20 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-Agent-Zero` | `PMOVES-Agent-Zero/python/api/csrf_token.py` | py, token | | `token` | 0.20 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-Open-Notebook` | `PMOVES-Open-Notebook/open_notebook/utils/token_utils.py` | py, token | | `token` | 0.20 | `pmoves/tools/youtube_po_token_capture.py` | `Pmoves-Health-wger` | `Pmoves-Health-wger/wger/utils/api_token.py` | py, token | +| `token` | 0.18 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-Archon` | `PMOVES-Archon/python/.venv/Lib/site-packages/prompt_toolkit/token.py` | py, token | | `token` | 0.18 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-HiRAG` | `PMOVES-HiRAG/eval/cal_tokens.py` | pmoves, py | | `token` | 0.15 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-Ultimate-TTS-Studio` | `PMOVES-Ultimate-TTS-Studio/fish_speech/tokenizer.py` | pmoves, py | | `token` | 0.10 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-Agent-Zero` | `PMOVES-Agent-Zero/python/helpers/tokens.py` | py | @@ -128,11 +133,13 @@ _Generated: 2026-03-02_ | `token` | 0.08 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-ToKenism-Multi` | `PMOVES-ToKenism-Multi/.claude/skills/tokenism-analysis/tools/export-metrics.ts` | tools | | `token` | 0.08 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-ToKenism-Multi` | `PMOVES-ToKenism-Multi/.claude/skills/tokenism-analysis/tools/run-simulation.ts` | tools | | `token` | 0.08 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-ToKenism-Multi` | `PMOVES-ToKenism-Multi/.claude/skills/tokenism-analysis/tools/validate-params.ts` | tools | +| `token` | 0.07 | `pmoves/tools/youtube_po_token_capture.py` | `PMOVES-Archon` | `PMOVES-Archon/python/.venv/Lib/site-packages/anthropic/types/message_count_tokens_tool_param.py` | py | | `user` | 0.33 | `pmoves/tools/create_supabase_boot_user.py` | `PMOVES-Agent-Zero` | `PMOVES-Agent-Zero/python/tools/notify_user.py` | py, tools, user | | `user` | 0.33 | `pmoves/tools/create_supabase_boot_user.py` | `PMOVES-Archon` | `PMOVES-Archon/external/PMOVES-Agent-Zero/python/tools/notify_user.py` | py, tools, user | | `user` | 0.33 | `pmoves/tools/create_supabase_boot_user.py` | `PMOVES-DoX` | `PMOVES-DoX/external/PMOVES-Agent-Zero/python/tools/notify_user.py` | py, tools, user | | `user` | 0.33 | `pmoves/tools/create_supabase_boot_user.py` | `pmoves/integrations/archon` | `pmoves/integrations/archon/external/PMOVES-Agent-Zero/python/tools/notify_user.py` | py, tools, user | | `user` | 0.30 | `pmoves/tools/create_supabase_boot_user.py` | `PMOVES-Creator` | `PMOVES-Creator/app/user_manager.py` | pmoves, py, user | +| `user` | 0.18 | `pmoves/tools/create_supabase_boot_user.py` | `PMOVES-Open-Notebook` | `PMOVES-Open-Notebook/.venv/Lib/site-packages/requests_toolbelt/utils/user_agent.py` | py, user | | `user` | 0.18 | `pmoves/tools/create_supabase_boot_user.py` | `PMOVES-Creator` | `PMOVES-Creator/comfy/diffusers_convert.py` | pmoves, py | | `user` | 0.18 | `pmoves/tools/create_supabase_boot_user.py` | `PMOVES-Creator` | `PMOVES-Creator/comfy/diffusers_load.py` | pmoves, py | | `user` | 0.17 | `pmoves/tools/create_supabase_boot_user.py` | `PMOVES-Pipecat` | `PMOVES-Pipecat/src/pipecat/turns/user_start/transcription_user_turn_start_strategy.py` | py, user | diff --git a/pmoves/docs/NEXT_STEPS.md b/pmoves/docs/NEXT_STEPS.md index a1e98ee869..8948e255f5 100644 --- a/pmoves/docs/NEXT_STEPS.md +++ b/pmoves/docs/NEXT_STEPS.md @@ -1,7 +1,41 @@ # PMOVES v5 • NEXT_STEPS Note: Consolidated plan index at pmoves/docs/PMOVES.AI PLANS/README_DOCS_INDEX.md. -_Last updated: 2026-03-07_ +_Last updated: 2026-03-08_ + +### Latest changes (Mar 8, 2026) — CI Runner Migration + RG-3 Automation +- **AB-9 mitigation:** Migrated 10 lightweight CI jobs from `[self-hosted, Linux, X64]` to `ubuntu-latest`: + - `sql-policy-lint`, `python-tests`, `webhook-smoke`, `yt-dlp-bump`, `deploy-gateway-agent` (validate only) + - `hardening-validation` (4/5 jobs; docker-bench kept on self-hosted with `vps` label) + - `build-images` (setup-matrix job only) +- Added `max-parallel` throttling: `build-images` matrix (4), `self-hosted-builds-hardened` CPU matrix (3) +- Added missing concurrency blocks: `codex-parity-advisory`, `webhook-smoke` +- Added QEMU/Buildx setup to `yt-dlp-bump` for multi-arch builds on GitHub-hosted runners +- **RG-3 automated:** New `supa-collation-refresh` and `supa-collation-check` Make targets; collation refresh runs automatically in `supa-start` bootstrap +- Recommendation: consolidate `self-hosted-builds.yml` (subset of hardened version) by disabling its push trigger + +### Latest changes (Mar 8, 2026) — Post-Merge Audit Sweep +- Post-merge production audit sweep completed after PRs `#823` and `#824` merged: + - `#823`: post-cleanup sitrep refresh (branch/stash/worktree hygiene + stale doc archival) + - `#824`: fix 8 broken links + 3 path mismatches in docs index (CodeRabbit review addressed) +- Static gate sweep: 6/7 PASS (secrets-audit timed out — auth-alignment confirms 0 errors) + - Submodule integrity: 40 gitlinks, 0 drifted, 0 conflicts + - Branch policy: 40 checked, DoX override acknowledged + - Tooling audit: 0 errors, 0 warnings +- Runtime verification snapshot: + - `smoke`: PASS (10/12 OK; Meilisearch + Neo4j pre-existing WARN) + - `model-readiness`: PASS (17/17, 0 failed, 1 TZ catalog warning) + - `monitoring-smoke`: PASS (Prometheus 36 active/28 healthy, 20 Grafana dashboards) + - `auth-alignment`: PASS (0 errors, 62 placeholder warnings) + - `GPU smoke (strict)`: PASS (v1 GPU optional warning only) +- Release gate spot-checks: + - RG-1 PASS, RG-2 PASS, RG-3 KNOWN (collation mismatch pre-existing), RG-4 PASS, RG-5 PASS (8 personas) +- CI/AB-9 status: all 4 runners offline, 4 queued runs identified as cancel candidates +- Live backlog snapshot: + - Open PRs: `0` + - Dependabot alerts: `1` (`1 medium`) + - Code scanning alerts: `0` +- Next focus: drain 4 stale queued CI runs, bring runners online for fresh CodeQL/GHCR verification ### Latest changes (Mar 7, 2026) - Merge wave completed on `main`: 8 PRs merged in 3 batches diff --git a/pmoves/docs/PRODUCTION_AUDIT_DASHBOARD.md b/pmoves/docs/PRODUCTION_AUDIT_DASHBOARD.md index b6cc0a40fe..1e31e39a54 100644 --- a/pmoves/docs/PRODUCTION_AUDIT_DASHBOARD.md +++ b/pmoves/docs/PRODUCTION_AUDIT_DASHBOARD.md @@ -3,14 +3,48 @@ > **Single source of truth** for PMOVES.AI production readiness. > Supersedes all individual audit documents accumulated Feb 7 -- Feb 18, 2026. -**Last Updated:** 2026-03-07 (8-PR merge wave + GHCR matrix gap analysis) +**Last Updated:** 2026-03-08 (post-merge audit sweep — PRs #823/#824) **Branch:** `PMOVES.AI-Edition-Hardened` (production release lane) -**Commit:** `96adc266` +**Commit:** `ba3c7f84` **Consolidated From:** 27 audit documents **Evidence:** live runbook execution on 2026-03-05 (`make ghcr-prepublish-inrepo-build`, strict local Trivy sweep logs under `pmoves/docs/logs/ghcr-local-prepublish/`) --- +## Latest Changes (Mar 8, 2026) + +- Post-merge audit sweep after PRs `#823` and `#824` merged to `main`: + - `#823`: docs index cleanup sitrep refresh (branch/stash/worktree hygiene + stale doc archival) + - `#824`: fix 8 broken links + 3 path mismatches in README_DOCS_INDEX (CodeRabbit comments addressed) +- **Static gate sweep (7 gates):** 6/7 PASS + - `submodule-layer-validate-all-strict`: PASS (all submodules `[ok]`) + - `submodule-branch-policy-check`: PASS (40 checked, DoX override acknowledged) + - `submodule-integrity-strict`: PASS (40 gitlinks, 0 drifted, 0 conflicts) + - `submodule-docs-audit-strict`: PASS (dossier regenerated) + - `integration-contract-check-baseline`: PASS (3/3 — template, health-wger, firefly-iii) + - `tooling-audit-strict`: PASS (errors=0 warnings=0, overlap_rows=124) + - `secrets-audit`: TIMEOUT (long-running scan — pre-existing; auth-alignment confirms 0 errors) +- **Runtime verification:** + - `smoke`: PASS (10/12 OK; Meilisearch + Neo4j WARN — pre-existing, not running locally) + - `model-readiness`: PASS (17/17 passed, 0 failed, 1 warning — TZ model catalog non-list payload) + - `monitoring-smoke`: PASS (Prometheus active=36 healthy=28, 20 Grafana dashboards, Loki ready) + - `auth-alignment`: PASS (0 errors, 62 warnings — placeholder credentials, pre-existing) + - `GPU smoke (strict)`: PASS (v2-gpu OK, v1-gpu optional endpoint returned HTTP 0 — expected) +- **Release gate spot-checks:** + - RG-1: PASS — `ui-dev-start` only in `bringup_with_ui.sh` (dev/prod orchestrator, not production service) + - RG-2: PASS — all compose port references use `${VAR:-default}` env-var patterns + - RG-3: AUTOMATED — `_supabase` DB collation mismatch now auto-refreshed via `supa-collation-refresh` in `supa-start`; `make -C pmoves supa-collation-check` available for manual verification + - RG-4: PASS — auth-alignment 0 errors + - RG-5: PASS — `persona_model_resolution` returns 8 rows (all personas grounded) +- **CI/AB-9 status:** + - All 4 self-hosted runners offline (pmoves-ai-lab-runner, pmoves-ai-lab-win, pmoves-hotfix-runner, pmoves-vps-runner) + - 4 queued runs: 2 from `#822` merge push (GHCR + CodeQL), 1 stale `#822` PR run, 1 stale Deploy Gateway Agent + - Queue guard identified all 4 as cancel candidates (non-PR or closed-PR events) + - **Mitigation applied:** 10 lightweight workflows migrated from `[self-hosted, Linux, X64]` to `ubuntu-latest` (sql-policy-lint, python-tests, webhook-smoke, yt-dlp-bump, deploy-gateway-agent validate job, hardening-validation 4/5 jobs, build-images setup-matrix). Matrix throttling added (`max-parallel: 3-4`) to build-images and self-hosted-builds-hardened. Missing concurrency blocks added to codex-parity-advisory and webhook-smoke. +- Live metrics: Open PRs `0`, Dependabot `1` (medium), Code Scanning `0` + +--- + ## Latest Changes (Mar 5, 2026) - GHCR production local-first validation widened from single-image checks to matrix-driven validation: @@ -145,7 +179,7 @@ | Metric | Value | |--------|-------| -| Quantitative snapshot timestamp | 2026-03-07 (live GitHub + local smoke/model-readiness snapshot) | +| Quantitative snapshot timestamp | 2026-03-08 (live GitHub + local smoke/model-readiness/GPU/monitoring snapshot) | | Total tracked items | 24 | | Resolved | 23 (+1 since last update) | | Active blockers | 1 (self-hosted queue starvation) | @@ -153,21 +187,21 @@ | High | 1 | | Medium | 0 | | Low | 0 | -| CodeQL alerts (open) | **0 open** (live GitHub API on 2026-03-07) | -| Dependabot alerts | **1 open** (`1 medium`; live GitHub API on 2026-03-07) | +| CodeQL alerts (open) | **0 open** (live GitHub API on 2026-03-08) | +| Dependabot alerts | **1 open** (`1 medium`; live GitHub API on 2026-03-08) | | Open PRs | **0** | | CI queue | Hosted gates healthy; self-hosted queue starvation persists on CodeQL/GHCR lanes | -### Runtime Verification Snapshot (2026-03-04) +### Runtime Verification Snapshot (2026-03-08) | Check | Result | Notes | |---|---|---| -| `make -C pmoves smoke` | PASS | Core production smoke completed with Agent Zero/geometry lanes green | -| `make -C pmoves model-readiness` | PASS | `14/14` passed; `0` failed; `0` warnings | -| Agent Zero published image health | PASS | `/healthz` returns `200` after compose PYTHONPATH + `pmoves.chit` shim | -| Strict GPU smoke | PASS | `GPU_SMOKE_STRICT=true make -C pmoves smoke-gpu` passed; optional v1 GPU endpoint returned warning only | -| Container health sitrep | PASS | `0` running unhealthy/restarting containers | -| Supabase CLI vector exclusion | PASS | `SUPABASE_CLI_EXCLUDE=vector` now supported in `supa-start` | +| `make -C pmoves smoke` | PASS | 10/12 OK; Meilisearch + Neo4j WARN (not running locally — pre-existing) | +| `make -C pmoves model-readiness` | PASS | `17/17` passed; `0` failed; `1` warning (TZ model catalog non-list payload) | +| `make -C pmoves monitoring-smoke` | PASS | Prometheus active=36 healthy=28; Grafana 20 dashboards; Loki ready | +| `make -C pmoves auth-alignment` | PASS | `0` errors; `62` warnings (placeholder creds — pre-existing) | +| Strict GPU smoke | PASS | `GPU_SMOKE_STRICT=true make -C pmoves smoke-gpu` passed; v1 GPU optional HTTP 0 | +| Persona grounding (RG-5) | PASS | `persona_model_resolution` returns `8` rows | ### Local Atomic Lanes (2026-03-02) @@ -465,8 +499,8 @@ rg -n "ui-dev-start|ui-dev-stop|ui-dev-logs|dev-start" pmoves/tools pmoves/Makef # RG-2: inspect hard-coded localhost/port assumptions in compose/env paths rg -n "localhost:[0-9]+|127\\.0\\.0\\.1:[0-9]+" pmoves/docker-compose*.yml pmoves/env.shared pmoves/tools -# RG-3: inspect Supabase/Postgres collation mismatch warnings after rebuild -docker compose logs --tail=200 supabase-db +# RG-3: Supabase collation check (automated via supa-collation-refresh in supa-start) +make -C pmoves supa-collation-check # RG-4: auth unification regression pass # Run JWT/key rotation flow and verify all core services re-auth @@ -533,6 +567,7 @@ If `generatedAt` is older than 24 hours, a `(stale)` indicator appears beside th | Date | Change | |------|--------| +| 2026-03-08 | **Post-merge audit sweep:** PRs #823/#824 merged. Static gates 6/7 PASS (secrets-audit timeout). Runtime: smoke PASS (10/12), model-readiness 17/17 PASS, monitoring-smoke PASS, auth-alignment 0 errors, GPU smoke PASS. Release gates: RG-1/2/4/5 PASS, RG-3 KNOWN (collation). CI: all 4 runners offline, 4 queued runs (cancel candidates). Live metrics: 0 PRs, 0 CodeQL, 1 Dependabot (medium). | | 2026-03-02 | **Live metrics sync (Codex):** refreshed executive summary from GitHub live data: CodeQL open alerts `36`, Dependabot open alerts `5`, open PRs `5`; CI snapshot synced to PR #758 head `db6b3a13` with self-hosted queue-capacity note. Ran queue guard and canceled stale queued runs `22565935122`, `22565935100`, `22565816518` to reduce deadlock pressure while preserving active PR lanes. | | 2026-03-02 | **Post-split-lane cleanup:** merged origin/main (PRs #752, #753), resolved conflicts, fixed env churn idempotency, addressed 13 CodeRabbit review comments (SQL grants, credential fallbacks, docs_sync hardening, PostgREST schema, bringup runtime detection). | | 2026-03-02 | **Split-lane merge closeout (Codex):** merged PMOVES-A2UI `#4`, PMOVES-Archon `#10`, and PMOVES-Archon `#11`; pushed final parent gitlink bump `a115a040` (A2UI + Archon + integrations/archon). | diff --git a/pmoves/docs/SUBMODULE_DOCS_DOSSIER.md b/pmoves/docs/SUBMODULE_DOCS_DOSSIER.md index 8001c0a948..c23a283860 100644 --- a/pmoves/docs/SUBMODULE_DOCS_DOSSIER.md +++ b/pmoves/docs/SUBMODULE_DOCS_DOSSIER.md @@ -1,5 +1,5 @@ # Submodule Docs Dossier -_Generated: 2026-02-26 18:23 UTC_ +_Generated: 2026-03-08 12:47 UTC_ ## Summary - Total submodules declared: **40** diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-A2UI.json b/pmoves/docs/evidence/submodule_layer/PMOVES-A2UI.json index 089254df08..3dbbd6e052 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-A2UI.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-A2UI.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:52 UTC", + "generated_at": "2026-03-08 12:44 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-A2UI.md b/pmoves/docs/evidence/submodule_layer/PMOVES-A2UI.md index c43f0c23dc..a1e892efd8 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-A2UI.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-A2UI.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:52 UTC_ +_Generated: 2026-03-08 12:44 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Agent-Zero.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Agent-Zero.json index 0f0a2ca9c8..129fd24ab0 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Agent-Zero.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Agent-Zero.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:52 UTC", + "generated_at": "2026-03-08 12:44 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, @@ -12,7 +12,7 @@ "path": "PMOVES-Agent-Zero", "url": "https://github.com/POWERFULMOVES/PMOVES-Agent-Zero.git", "status_prefix": " ", - "commit": "76923745d7601bcd5d8dcc441dee97449b65ef99", + "commit": "2e000aa304e52ed47ca4d5eb4a9ce64a35c916a2", "initialized": true, "remote_commit_reachable": "local", "required_files_any_ok": true, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Agent-Zero.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Agent-Zero.md index 745058c027..2aa0817192 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Agent-Zero.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Agent-Zero.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:52 UTC_ +_Generated: 2026-03-08 12:44 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-AgentGym.json b/pmoves/docs/evidence/submodule_layer/PMOVES-AgentGym.json index 3d4f5bafe9..dd3767621c 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-AgentGym.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-AgentGym.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:52 UTC", + "generated_at": "2026-03-08 12:44 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-AgentGym.md b/pmoves/docs/evidence/submodule_layer/PMOVES-AgentGym.md index fb4bd35239..8840b953c0 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-AgentGym.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-AgentGym.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:52 UTC_ +_Generated: 2026-03-08 12:44 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Archon.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Archon.json index 4a7863d3aa..3b5cd8c2b2 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Archon.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Archon.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:53 UTC", + "generated_at": "2026-03-08 12:45 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Archon.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Archon.md index 85f225f5f7..1ae72b4733 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Archon.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Archon.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:53 UTC_ +_Generated: 2026-03-08 12:45 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-BoTZ.json b/pmoves/docs/evidence/submodule_layer/PMOVES-BoTZ.json index dc3f1ecf90..2f2fdfed6b 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-BoTZ.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-BoTZ.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:53 UTC", + "generated_at": "2026-03-08 12:45 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, @@ -12,7 +12,7 @@ "path": "PMOVES-BoTZ", "url": "https://github.com/POWERFULMOVES/PMOVES-BoTZ.git", "status_prefix": " ", - "commit": "94529789f8453b27448a1bfb3e41e3092c05807b", + "commit": "4382e2704ae7d6a938768b5434a73fd62410801c", "initialized": true, "remote_commit_reachable": "local", "required_files_any_ok": true, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-BoTZ.md b/pmoves/docs/evidence/submodule_layer/PMOVES-BoTZ.md index 0849a1bb6a..8381244e19 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-BoTZ.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-BoTZ.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:53 UTC_ +_Generated: 2026-03-08 12:45 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-BotZ-gateway.json b/pmoves/docs/evidence/submodule_layer/PMOVES-BotZ-gateway.json index c279e6288a..d083d7d7da 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-BotZ-gateway.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-BotZ-gateway.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:53 UTC", + "generated_at": "2026-03-08 12:45 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, @@ -12,7 +12,7 @@ "path": "PMOVES-BotZ-gateway", "url": "https://github.com/POWERFULMOVES/PMOVES-BotZ-gateway.git", "status_prefix": " ", - "commit": "d4db42419f7a072f9c9c8139ed68b40de741fd38", + "commit": "0dc9aaafb4deafabe851a266b904ec089a17d948", "initialized": true, "remote_commit_reachable": "local", "required_files_any_ok": true, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-BotZ-gateway.md b/pmoves/docs/evidence/submodule_layer/PMOVES-BotZ-gateway.md index 7bc4aba6fc..1183fd7883 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-BotZ-gateway.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-BotZ-gateway.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:53 UTC_ +_Generated: 2026-03-08 12:45 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Creator.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Creator.json index d7ae1f17f2..cb0c49b45f 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Creator.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Creator.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:53 UTC", + "generated_at": "2026-03-08 12:45 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Creator.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Creator.md index 9a816f85eb..38416df403 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Creator.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Creator.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:53 UTC_ +_Generated: 2026-03-08 12:45 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Danger-infra.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Danger-infra.json index 4d8061ac07..5cef26f35a 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Danger-infra.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Danger-infra.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:53 UTC", + "generated_at": "2026-03-08 12:45 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Danger-infra.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Danger-infra.md index ea72fc1267..1e5dc91067 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Danger-infra.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Danger-infra.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:53 UTC_ +_Generated: 2026-03-08 12:45 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Deep-Serch.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Deep-Serch.json index 2bc406222b..70bb3fb519 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Deep-Serch.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Deep-Serch.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:53 UTC", + "generated_at": "2026-03-08 12:45 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Deep-Serch.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Deep-Serch.md index 832b97783e..2558db94b4 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Deep-Serch.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Deep-Serch.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:53 UTC_ +_Generated: 2026-03-08 12:45 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-DoX.json b/pmoves/docs/evidence/submodule_layer/PMOVES-DoX.json index 6564b4afff..096060c151 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-DoX.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-DoX.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:53 UTC", + "generated_at": "2026-03-08 12:45 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, @@ -11,8 +11,8 @@ "name": "PMOVES-DoX", "path": "PMOVES-DoX", "url": "https://github.com/POWERFULMOVES/PMOVES-DoX.git", - "status_prefix": "+", - "commit": "035364ce62223b12a7653b4e3052e2c22e7a9d50", + "status_prefix": " ", + "commit": "24e1be22e3baa653214a5e5f9084f78d4a143baf", "initialized": true, "remote_commit_reachable": "local", "required_files_any_ok": true, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-DoX.md b/pmoves/docs/evidence/submodule_layer/PMOVES-DoX.md index ab6fa3764c..ea14fd8115 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-DoX.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-DoX.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:53 UTC_ +_Generated: 2026-03-08 12:45 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` @@ -11,7 +11,7 @@ _Generated: 2026-03-03 03:53 UTC_ ## Matrix | Submodule | Initialized | Status | Remote Commit | Docs(any) | Top-level Dossier | Nested .gitmodules | Python Compile | | --- | --- | --- | --- | --- | --- | --- | --- | -| `PMOVES-DoX` | yes | `+` | `local` | yes | yes | ok | `skip` | +| `PMOVES-DoX` | yes | ` ` | `local` | yes | yes | ok | `skip` | ## Findings - No findings. diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room-Desktop.json b/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room-Desktop.json index 43a80004b7..9266a10f56 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room-Desktop.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room-Desktop.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:54 UTC", + "generated_at": "2026-03-08 12:46 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room-Desktop.md b/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room-Desktop.md index a9879ca2f1..eef7063f6d 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room-Desktop.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room-Desktop.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:54 UTC_ +_Generated: 2026-03-08 12:46 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room.json b/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room.json index 12422be33a..4b931ffa84 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:54 UTC", + "generated_at": "2026-03-08 12:46 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room.md b/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room.md index 3c47bcbaee..4ff4e2b485 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-E2B-Danger-Room.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:54 UTC_ +_Generated: 2026-03-08 12:46 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-E2b-Spells.json b/pmoves/docs/evidence/submodule_layer/PMOVES-E2b-Spells.json index 20172f078f..9d807001c1 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-E2b-Spells.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-E2b-Spells.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:54 UTC", + "generated_at": "2026-03-08 12:46 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-E2b-Spells.md b/pmoves/docs/evidence/submodule_layer/PMOVES-E2b-Spells.md index f8a3182688..471ddbec7c 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-E2b-Spells.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-E2b-Spells.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:54 UTC_ +_Generated: 2026-03-08 12:46 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Headscale.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Headscale.json index 019a487702..ec3b4f0fde 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Headscale.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Headscale.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:54 UTC", + "generated_at": "2026-03-08 12:46 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Headscale.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Headscale.md index be64575996..e2695ad8ec 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Headscale.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Headscale.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:54 UTC_ +_Generated: 2026-03-08 12:46 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-HiRAG.json b/pmoves/docs/evidence/submodule_layer/PMOVES-HiRAG.json index c75e4561f3..ddabfe9521 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-HiRAG.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-HiRAG.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:54 UTC", + "generated_at": "2026-03-08 12:46 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-HiRAG.md b/pmoves/docs/evidence/submodule_layer/PMOVES-HiRAG.md index df8d97ad4f..79efffb046 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-HiRAG.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-HiRAG.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:54 UTC_ +_Generated: 2026-03-08 12:46 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Jellyfin.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Jellyfin.json index ae76dd706c..c0f929f426 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Jellyfin.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Jellyfin.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:54 UTC", + "generated_at": "2026-03-08 12:46 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Jellyfin.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Jellyfin.md index 69ab2fa74e..9896556ddd 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Jellyfin.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Jellyfin.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:54 UTC_ +_Generated: 2026-03-08 12:46 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-MAI-UI.json b/pmoves/docs/evidence/submodule_layer/PMOVES-MAI-UI.json index 35550a58ef..8b7fb63b33 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-MAI-UI.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-MAI-UI.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:55 UTC", + "generated_at": "2026-03-08 12:46 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-MAI-UI.md b/pmoves/docs/evidence/submodule_layer/PMOVES-MAI-UI.md index 07992b8c48..e9395bc65f 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-MAI-UI.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-MAI-UI.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:55 UTC_ +_Generated: 2026-03-08 12:46 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Open-Notebook.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Open-Notebook.json index ff89746556..061ecceb6c 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Open-Notebook.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Open-Notebook.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:55 UTC", + "generated_at": "2026-03-08 12:47 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, @@ -11,8 +11,8 @@ "name": "PMOVES-Open-Notebook", "path": "PMOVES-Open-Notebook", "url": "https://github.com/POWERFULMOVES/PMOVES-Open-Notebook.git", - "status_prefix": "+", - "commit": "91336e7b3b28ed75dfa27b2cbbd39cd8dd31d8b9", + "status_prefix": " ", + "commit": "e9ccae69e49b7b6dd388c3956202eedc0fb27e4c", "initialized": true, "remote_commit_reachable": "local", "required_files_any_ok": true, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Open-Notebook.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Open-Notebook.md index f5fdba4afc..4d55b91e62 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Open-Notebook.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Open-Notebook.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:55 UTC_ +_Generated: 2026-03-08 12:47 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` @@ -11,7 +11,7 @@ _Generated: 2026-03-03 03:55 UTC_ ## Matrix | Submodule | Initialized | Status | Remote Commit | Docs(any) | Top-level Dossier | Nested .gitmodules | Python Compile | | --- | --- | --- | --- | --- | --- | --- | --- | -| `PMOVES-Open-Notebook` | yes | `+` | `local` | yes | yes | ok | `skip` | +| `PMOVES-Open-Notebook` | yes | ` ` | `local` | yes | yes | ok | `skip` | ## Findings - No findings. diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Pinokio-Ultimate-TTS-Studio.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Pinokio-Ultimate-TTS-Studio.json index 66d3f9d1e4..72166397be 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Pinokio-Ultimate-TTS-Studio.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Pinokio-Ultimate-TTS-Studio.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:55 UTC", + "generated_at": "2026-03-08 12:47 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Pinokio-Ultimate-TTS-Studio.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Pinokio-Ultimate-TTS-Studio.md index 72a468f33f..ff90e9f633 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Pinokio-Ultimate-TTS-Studio.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Pinokio-Ultimate-TTS-Studio.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:55 UTC_ +_Generated: 2026-03-08 12:47 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Pipecat.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Pipecat.json index a6d47dbc21..152f508125 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Pipecat.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Pipecat.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:55 UTC", + "generated_at": "2026-03-08 12:47 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Pipecat.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Pipecat.md index 767ea479b3..2507e329d4 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Pipecat.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Pipecat.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:55 UTC_ +_Generated: 2026-03-08 12:47 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Remote-View.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Remote-View.json index 13a2fcac03..c89d72d0e6 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Remote-View.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Remote-View.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:55 UTC", + "generated_at": "2026-03-08 12:47 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Remote-View.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Remote-View.md index 58c467297e..1ac91beaf7 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Remote-View.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Remote-View.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:55 UTC_ +_Generated: 2026-03-08 12:47 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Tailscale.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Tailscale.json index 08be1a6873..a448b36978 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Tailscale.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Tailscale.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:55 UTC", + "generated_at": "2026-03-08 12:47 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Tailscale.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Tailscale.md index 368b75690b..1e56e375a9 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Tailscale.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Tailscale.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:55 UTC_ +_Generated: 2026-03-08 12:47 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-ToKenism-Multi.json b/pmoves/docs/evidence/submodule_layer/PMOVES-ToKenism-Multi.json index 6d856e8550..576d56787a 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-ToKenism-Multi.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-ToKenism-Multi.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:56 UTC", + "generated_at": "2026-03-08 12:47 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-ToKenism-Multi.md b/pmoves/docs/evidence/submodule_layer/PMOVES-ToKenism-Multi.md index 500ab5eaf6..65339cb035 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-ToKenism-Multi.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-ToKenism-Multi.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:56 UTC_ +_Generated: 2026-03-08 12:47 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Ultimate-TTS-Studio.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Ultimate-TTS-Studio.json index 02fa2f067e..029d6dc195 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Ultimate-TTS-Studio.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Ultimate-TTS-Studio.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:56 UTC", + "generated_at": "2026-03-08 12:48 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Ultimate-TTS-Studio.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Ultimate-TTS-Studio.md index 5742060ebc..e5d2e8522a 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Ultimate-TTS-Studio.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Ultimate-TTS-Studio.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:56 UTC_ +_Generated: 2026-03-08 12:48 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Wealth.json b/pmoves/docs/evidence/submodule_layer/PMOVES-Wealth.json index 10ea3476f8..18748eb0db 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Wealth.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Wealth.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:56 UTC", + "generated_at": "2026-03-08 12:48 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-Wealth.md b/pmoves/docs/evidence/submodule_layer/PMOVES-Wealth.md index bf2a49d533..ee0d51513d 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-Wealth.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-Wealth.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:56 UTC_ +_Generated: 2026-03-08 12:48 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-crush.json b/pmoves/docs/evidence/submodule_layer/PMOVES-crush.json index f1e4a66039..6bb4859ce5 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-crush.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-crush.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:53 UTC", + "generated_at": "2026-03-08 12:45 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-crush.md b/pmoves/docs/evidence/submodule_layer/PMOVES-crush.md index a2d50a535b..23ae923e30 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-crush.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-crush.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:53 UTC_ +_Generated: 2026-03-08 12:45 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-llama-throughput-lab.json b/pmoves/docs/evidence/submodule_layer/PMOVES-llama-throughput-lab.json index 2b9f1a6ca3..0b714d9398 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-llama-throughput-lab.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-llama-throughput-lab.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:55 UTC", + "generated_at": "2026-03-08 12:46 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-llama-throughput-lab.md b/pmoves/docs/evidence/submodule_layer/PMOVES-llama-throughput-lab.md index 161dbdd609..bfd08767c7 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-llama-throughput-lab.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-llama-throughput-lab.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:55 UTC_ +_Generated: 2026-03-08 12:46 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-n8n.json b/pmoves/docs/evidence/submodule_layer/PMOVES-n8n.json index fc360e2d55..a35e7dd4bb 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-n8n.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-n8n.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:55 UTC", + "generated_at": "2026-03-08 12:47 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-n8n.md b/pmoves/docs/evidence/submodule_layer/PMOVES-n8n.md index 316f93676a..5ec82ba2c0 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-n8n.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-n8n.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:55 UTC_ +_Generated: 2026-03-08 12:47 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-supabase.json b/pmoves/docs/evidence/submodule_layer/PMOVES-supabase.json index 3170b9d87e..b1768e898b 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-supabase.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-supabase.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:55 UTC", + "generated_at": "2026-03-08 12:47 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-supabase.md b/pmoves/docs/evidence/submodule_layer/PMOVES-supabase.md index 0ffa6aacb9..4a56278340 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-supabase.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-supabase.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:55 UTC_ +_Generated: 2026-03-08 12:47 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-surf.json b/pmoves/docs/evidence/submodule_layer/PMOVES-surf.json index 9dba07f086..89add9f700 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-surf.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-surf.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:55 UTC", + "generated_at": "2026-03-08 12:47 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-surf.md b/pmoves/docs/evidence/submodule_layer/PMOVES-surf.md index 07a91551c5..d487e0d1ec 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-surf.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-surf.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:55 UTC_ +_Generated: 2026-03-08 12:47 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-tensorzero.json b/pmoves/docs/evidence/submodule_layer/PMOVES-tensorzero.json index f5b3480f5f..5c9044d0b8 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-tensorzero.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-tensorzero.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:55 UTC", + "generated_at": "2026-03-08 12:47 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, @@ -12,7 +12,7 @@ "path": "PMOVES-tensorzero", "url": "https://github.com/POWERFULMOVES/PMOVES-tensorzero.git", "status_prefix": " ", - "commit": "f14bdf66bf409112fea4a3d0d38f82315d2fc80c", + "commit": "d71f4d14f1026e165243dfa281520ae7a84b0cc5", "initialized": true, "remote_commit_reachable": "local", "required_files_any_ok": true, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-tensorzero.md b/pmoves/docs/evidence/submodule_layer/PMOVES-tensorzero.md index e17d947c55..e781e1c7cc 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-tensorzero.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-tensorzero.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:55 UTC_ +_Generated: 2026-03-08 12:47 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-transcribe-and-fetch.json b/pmoves/docs/evidence/submodule_layer/PMOVES-transcribe-and-fetch.json index 7bd930487d..713e63ceef 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-transcribe-and-fetch.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-transcribe-and-fetch.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:56 UTC", + "generated_at": "2026-03-08 12:48 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, @@ -11,8 +11,8 @@ "name": "PMOVES-transcribe-and-fetch", "path": "PMOVES-transcribe-and-fetch", "url": "https://github.com/POWERFULMOVES/PMOVES-transcribe-and-fetch.git", - "status_prefix": "+", - "commit": "f4d651590a6eb092abacb4baadc9660e95ba706a", + "status_prefix": " ", + "commit": "5a57ca00185c6e04527cd2962feb2ac90491a0ad", "initialized": true, "remote_commit_reachable": "local", "required_files_any_ok": true, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES-transcribe-and-fetch.md b/pmoves/docs/evidence/submodule_layer/PMOVES-transcribe-and-fetch.md index 517b696c71..085fdbe244 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES-transcribe-and-fetch.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES-transcribe-and-fetch.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:56 UTC_ +_Generated: 2026-03-08 12:48 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` @@ -11,7 +11,7 @@ _Generated: 2026-03-03 03:56 UTC_ ## Matrix | Submodule | Initialized | Status | Remote Commit | Docs(any) | Top-level Dossier | Nested .gitmodules | Python Compile | | --- | --- | --- | --- | --- | --- | --- | --- | -| `PMOVES-transcribe-and-fetch` | yes | `+` | `local` | yes | yes | ok | `skip` | +| `PMOVES-transcribe-and-fetch` | yes | ` ` | `local` | yes | yes | ok | `skip` | ## Findings - No findings. diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES.YT.json b/pmoves/docs/evidence/submodule_layer/PMOVES.YT.json index 1a1e943786..7e3be4aaf1 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES.YT.json +++ b/pmoves/docs/evidence/submodule_layer/PMOVES.YT.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:56 UTC", + "generated_at": "2026-03-08 12:48 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/PMOVES.YT.md b/pmoves/docs/evidence/submodule_layer/PMOVES.YT.md index 16eecf685d..8e2937e32d 100644 --- a/pmoves/docs/evidence/submodule_layer/PMOVES.YT.md +++ b/pmoves/docs/evidence/submodule_layer/PMOVES.YT.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:56 UTC_ +_Generated: 2026-03-08 12:48 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/Pmoves-AgentGym-RL.json b/pmoves/docs/evidence/submodule_layer/Pmoves-AgentGym-RL.json index 6a71349855..76037feef9 100644 --- a/pmoves/docs/evidence/submodule_layer/Pmoves-AgentGym-RL.json +++ b/pmoves/docs/evidence/submodule_layer/Pmoves-AgentGym-RL.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:53 UTC", + "generated_at": "2026-03-08 12:45 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/Pmoves-AgentGym-RL.md b/pmoves/docs/evidence/submodule_layer/Pmoves-AgentGym-RL.md index 65cd4268e5..d715500085 100644 --- a/pmoves/docs/evidence/submodule_layer/Pmoves-AgentGym-RL.md +++ b/pmoves/docs/evidence/submodule_layer/Pmoves-AgentGym-RL.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:53 UTC_ +_Generated: 2026-03-08 12:45 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/Pmoves-Health-wger.json b/pmoves/docs/evidence/submodule_layer/Pmoves-Health-wger.json index 84203a5ff9..d2b618ec69 100644 --- a/pmoves/docs/evidence/submodule_layer/Pmoves-Health-wger.json +++ b/pmoves/docs/evidence/submodule_layer/Pmoves-Health-wger.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:54 UTC", + "generated_at": "2026-03-08 12:46 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/Pmoves-Health-wger.md b/pmoves/docs/evidence/submodule_layer/Pmoves-Health-wger.md index 25f6473f40..18a1b4083f 100644 --- a/pmoves/docs/evidence/submodule_layer/Pmoves-Health-wger.md +++ b/pmoves/docs/evidence/submodule_layer/Pmoves-Health-wger.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:54 UTC_ +_Generated: 2026-03-08 12:46 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/Pmoves-Jellyfin-AI-Media-Stack.json b/pmoves/docs/evidence/submodule_layer/Pmoves-Jellyfin-AI-Media-Stack.json index eef7eb08e3..65adb2c347 100644 --- a/pmoves/docs/evidence/submodule_layer/Pmoves-Jellyfin-AI-Media-Stack.json +++ b/pmoves/docs/evidence/submodule_layer/Pmoves-Jellyfin-AI-Media-Stack.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:54 UTC", + "generated_at": "2026-03-08 12:46 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/Pmoves-Jellyfin-AI-Media-Stack.md b/pmoves/docs/evidence/submodule_layer/Pmoves-Jellyfin-AI-Media-Stack.md index f95c5a4d6c..b87d9c4e51 100644 --- a/pmoves/docs/evidence/submodule_layer/Pmoves-Jellyfin-AI-Media-Stack.md +++ b/pmoves/docs/evidence/submodule_layer/Pmoves-Jellyfin-AI-Media-Stack.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:54 UTC_ +_Generated: 2026-03-08 12:46 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/Pmoves-cipher.json b/pmoves/docs/evidence/submodule_layer/Pmoves-cipher.json index b313896bbf..4920845236 100644 --- a/pmoves/docs/evidence/submodule_layer/Pmoves-cipher.json +++ b/pmoves/docs/evidence/submodule_layer/Pmoves-cipher.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:53 UTC", + "generated_at": "2026-03-08 12:45 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, @@ -11,8 +11,8 @@ "name": "Pmoves-cipher", "path": "Pmoves-cipher", "url": "https://github.com/POWERFULMOVES/Pmoves-cipher.git", - "status_prefix": "+", - "commit": "cad2c0233ff7daa44877b84742faec6dd947dfe1", + "status_prefix": " ", + "commit": "2bd33b9d2dc8f7974c5bf995375658f291bab7c2", "initialized": true, "remote_commit_reachable": "local", "required_files_any_ok": true, diff --git a/pmoves/docs/evidence/submodule_layer/Pmoves-cipher.md b/pmoves/docs/evidence/submodule_layer/Pmoves-cipher.md index caea6363b0..88e416ceb1 100644 --- a/pmoves/docs/evidence/submodule_layer/Pmoves-cipher.md +++ b/pmoves/docs/evidence/submodule_layer/Pmoves-cipher.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:53 UTC_ +_Generated: 2026-03-08 12:45 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` @@ -11,7 +11,7 @@ _Generated: 2026-03-03 03:53 UTC_ ## Matrix | Submodule | Initialized | Status | Remote Commit | Docs(any) | Top-level Dossier | Nested .gitmodules | Python Compile | | --- | --- | --- | --- | --- | --- | --- | --- | -| `Pmoves-cipher` | yes | `+` | `local` | yes | yes | ok | `skip` | +| `Pmoves-cipher` | yes | ` ` | `local` | yes | yes | ok | `skip` | ## Findings - No findings. diff --git a/pmoves/docs/evidence/submodule_layer/Pmoves-hyperdimensions.json b/pmoves/docs/evidence/submodule_layer/Pmoves-hyperdimensions.json index e4a6d4454f..3b49b8ce6f 100644 --- a/pmoves/docs/evidence/submodule_layer/Pmoves-hyperdimensions.json +++ b/pmoves/docs/evidence/submodule_layer/Pmoves-hyperdimensions.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:54 UTC", + "generated_at": "2026-03-08 12:46 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/Pmoves-hyperdimensions.md b/pmoves/docs/evidence/submodule_layer/Pmoves-hyperdimensions.md index 919bf87533..3bd32f7523 100644 --- a/pmoves/docs/evidence/submodule_layer/Pmoves-hyperdimensions.md +++ b/pmoves/docs/evidence/submodule_layer/Pmoves-hyperdimensions.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:54 UTC_ +_Generated: 2026-03-08 12:46 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/pmoves-e2b-mcp-server.json b/pmoves/docs/evidence/submodule_layer/pmoves-e2b-mcp-server.json index f6efb3e956..b547965177 100644 --- a/pmoves/docs/evidence/submodule_layer/pmoves-e2b-mcp-server.json +++ b/pmoves/docs/evidence/submodule_layer/pmoves-e2b-mcp-server.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:54 UTC", + "generated_at": "2026-03-08 12:46 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/pmoves-e2b-mcp-server.md b/pmoves/docs/evidence/submodule_layer/pmoves-e2b-mcp-server.md index 3a1d878f4f..ce9aabaaf7 100644 --- a/pmoves/docs/evidence/submodule_layer/pmoves-e2b-mcp-server.md +++ b/pmoves/docs/evidence/submodule_layer/pmoves-e2b-mcp-server.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:54 UTC_ +_Generated: 2026-03-08 12:46 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/docs/evidence/submodule_layer/pmoves__integrations__archon.json b/pmoves/docs/evidence/submodule_layer/pmoves__integrations__archon.json index 0ec120b34c..5aa1842d98 100644 --- a/pmoves/docs/evidence/submodule_layer/pmoves__integrations__archon.json +++ b/pmoves/docs/evidence/submodule_layer/pmoves__integrations__archon.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-03 03:56 UTC", + "generated_at": "2026-03-08 12:48 UTC", "manifest": "pmoves/configs/submodule_layer_validation_manifest.json", "summary": { "submodules": 1, diff --git a/pmoves/docs/evidence/submodule_layer/pmoves__integrations__archon.md b/pmoves/docs/evidence/submodule_layer/pmoves__integrations__archon.md index d6479bf504..22283969bb 100644 --- a/pmoves/docs/evidence/submodule_layer/pmoves__integrations__archon.md +++ b/pmoves/docs/evidence/submodule_layer/pmoves__integrations__archon.md @@ -1,5 +1,5 @@ # Submodule Layer Validation -_Generated: 2026-03-03 03:56 UTC_ +_Generated: 2026-03-08 12:48 UTC_ ## Summary - Manifest: `pmoves/configs/submodule_layer_validation_manifest.json` diff --git a/pmoves/examples/distributed/vps/README.md b/pmoves/examples/distributed/vps/README.md index 04dffa1dc1..45995ec763 100644 --- a/pmoves/examples/distributed/vps/README.md +++ b/pmoves/examples/distributed/vps/README.md @@ -7,7 +7,7 @@ Example configuration for deploying PMOVES submodules with a hybrid VPS and home **Hostinger VPS Cluster:** - **KVM4-1** - API Gateway (BoTZ MCP Gateway, reverse proxy) - **KVM4-2** - Data Services (DoX Backend, NATS) -- **KVM2** - Exit Node (Tailscale/WireGuard exit) +- **KVM2** - Exit Node (Tailscale exit node) **Home Network:** - **GPU Workstations** - Tokenism, local inference, development @@ -34,7 +34,7 @@ Example configuration for deploying PMOVES submodules with a hybrid VPS and home │ │ │ │ │ │ └────────────────────────┼───────────────────────┘ │ │ │ │ -│ WireGuard/Tailscale │ +│ Tailscale Mesh │ │ │ │ ├─────────────────────────────────────┼───────────────────────────────────────┤ │ Home Network │ @@ -83,33 +83,34 @@ ufw allow 4222/tcp # NATS (restrict to home IP) ufw enable ``` -### 2. WireGuard VPN Setup +### 2. Tailscale Mesh Setup -On KVM2 (exit node): +On KVM4-1 and KVM4-2: ```bash -apt install wireguard - -# Generate keys -wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey - -# Configure /etc/wireguard/wg0.conf -cat > /etc/wireguard/wg0.conf << 'EOF' -[Interface] -PrivateKey = -Address = 10.0.0.1/24 -ListenPort = 51820 -PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE -PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE - -[Peer] -# Home network -PublicKey = -AllowedIPs = 192.168.1.0/24, 10.0.0.2/32 +# Install Tailscale +curl -fsSL https://tailscale.com/install.sh | sh + +# Join mesh with tagged auth key (tagged keys auto-disable key expiry) +# Generate at https://login.tailscale.com/admin/settings/keys +tailscale up --auth-key tskey-xxx --hostname --accept-routes --accept-dns +``` + +On KVM2 (exit node), also enable IP forwarding and advertise: + +```bash +# Enable IP forwarding +sysctl -w net.ipv4.ip_forward=1 +sysctl -w net.ipv6.conf.all.forwarding=1 +cat > /etc/sysctl.d/99-tailscale-exit-node.conf <<'EOF' +net.ipv4.ip_forward = 1 +net.ipv6.conf.all.forwarding = 1 EOF -systemctl enable wg-quick@wg0 -systemctl start wg-quick@wg0 +# Advertise as exit node +tailscale up --auth-key tskey-xxx --hostname pmoves-kvm2 --advertise-exit-node --accept-routes --accept-dns + +# Approve exit node in admin console: https://login.tailscale.com/admin/machines ``` ### 3. Let's Encrypt Certificates @@ -161,8 +162,9 @@ docker compose -f docker-compose.yml -f docker-compose.distributed.yml \ cd ~/PMOVES-ToKenism-Multi cp /path/to/examples/vps/home-tokenism.env .env -# Connect via WireGuard -wg-quick up wg0 +# Verify Tailscale mesh connectivity +tailscale status +tailscale ping pmoves-kvm4-2 docker compose up -d ``` @@ -236,9 +238,9 @@ server { ufw allow from 192.168.1.0/24 to any port 2091 # BoTZ from home ufw allow 443/tcp # Public HTTPS -# KVM4-2 (Data Services) -ufw allow from 10.0.0.0/24 to any port 8484 # DoX from WireGuard -ufw allow from 10.0.0.0/24 to any port 4222 # NATS from WireGuard +# KVM4-2 (Data Services) — allow traffic from Tailscale interface +ufw allow in on tailscale0 to any port 8484 # DoX from Tailscale mesh +ufw allow in on tailscale0 to any port 4222 # NATS from Tailscale mesh ``` ### 2. Rate Limiting @@ -303,9 +305,10 @@ scrape_configs: ### VPS Cannot Reach Home Network -1. Check WireGuard status: `wg show` -2. Verify routing: `ip route show` -3. Test connectivity: `ping 10.0.0.2` +1. Check Tailscale status: `tailscale status` +2. Ping the target node: `tailscale ping pmoves-kvm4-2` +3. Check key expiry: `tailscale debug key-expiry` +4. Verify routing: `ip route show` ### SSL Certificate Issues diff --git a/pmoves/examples/distributed/vps/kvm4-1.env b/pmoves/examples/distributed/vps/kvm4-1.env index ea788e25ba..1c6b8f2b81 100644 --- a/pmoves/examples/distributed/vps/kvm4-1.env +++ b/pmoves/examples/distributed/vps/kvm4-1.env @@ -14,40 +14,44 @@ MCP_BRIDGE_PORT=8100 # Authentication (required for public VPS) SUPABASE_JWT_SECRET=your-strong-jwt-secret-here -# TensorZero (on home network via WireGuard) -# Option A: Run TensorZero on VPS (CPU-only) -# TENSORZERO_URL=http://localhost:3030 -# Option B: Connect to home network TensorZero -TENSORZERO_HOST=10.0.0.2 -TENSORZERO_URL=http://10.0.0.2:3030 - -# DoX (on KVM4-2) -DOX_HOST=kvm4-2.internal -DOX_BACKEND_URL=http://kvm4-2.internal:8484 - -# Tokenism (home network) -TOKENISM_HOST=10.0.0.3 -TOKENISM_URL=http://10.0.0.3:5000 - -# NATS (on KVM4-2) -NATS_HOST=kvm4-2.internal -NATS_URL=nats://kvm4-2.internal:4222 - -# Hi-RAG (home network or disabled) -HIRAG_HOST=10.0.0.2 -HIRAG_URL=http://10.0.0.2:8086 - -# Supabase (home network) -SUPABASE_HOST=10.0.0.2 -SUPABASE_URL=http://10.0.0.2:3010 - -# Disable local Ollama (use home network GPU) -# VL Sentinel will use remote Ollama -OLLAMA_HOST=10.0.0.2 -OLLAMA_BASE_URL=http://10.0.0.2:11434 +# TensorZero (local on this VPS or via Tailscale to home) +# Host-level port. Containers use http://tensorzero:3000 via compose network. +# Option A: Run TensorZero on VPS (CPU-only, default) +TENSORZERO_URL=http://localhost:3030 +# Option B: Connect to home network TensorZero via Tailscale +# TENSORZERO_HOST=pmoves-home +# TENSORZERO_URL=http://pmoves-home:3030 + +# DoX (on KVM4-2 via Tailscale) +DOX_HOST=pmoves-kvm4-2 +DOX_BACKEND_URL=http://pmoves-kvm4-2:8484 + +# Tokenism (home network via Tailscale) +TOKENISM_HOST=pmoves-home +TOKENISM_URL=http://pmoves-home:5000 + +# NATS (on KVM4-2 via Tailscale, with auth) +NATS_HOST=pmoves-kvm4-2 +NATS_URL=nats://nats:pmoves@pmoves-kvm4-2:4222 + +# Hi-RAG (home network via Tailscale or disabled) +HIRAG_HOST=pmoves-home +HIRAG_URL=http://pmoves-home:8086 + +# Supabase (home network via Tailscale) +SUPABASE_HOST=pmoves-home +SUPABASE_URL=http://pmoves-home:3010 + +# Disable local Ollama (use home network GPU via Tailscale) +OLLAMA_HOST=pmoves-home +OLLAMA_BASE_URL=http://pmoves-home:11434 VL_PROVIDER=ollama VL_MODEL=llava +# Hostinger API (for MCP tools) +# Set via CHIT secrets or shell environment — not self-referential in env_file context +# HOSTINGER_API_KEY= + # CPU-only mode (no GPU on VPS) DEFAULT_DEVICE=cpu diff --git a/pmoves/examples/distributed/vps/kvm4-2.env b/pmoves/examples/distributed/vps/kvm4-2.env index da7db14a44..d4183470be 100644 --- a/pmoves/examples/distributed/vps/kvm4-2.env +++ b/pmoves/examples/distributed/vps/kvm4-2.env @@ -9,29 +9,30 @@ DISTRIBUTED_SERVICES=true DOX_HOST=0.0.0.0 DOX_PORT=8484 -# NATS (local to this VPS, with TLS) +# NATS (local to this VPS, with auth) +# Bound to 0.0.0.0 for cross-node access — TLS not required because +# Tailscale provides encryption in transit between mesh nodes. +# Access control via UFW + Tailscale ACLs. NATS_HOST=0.0.0.0 NATS_PORT=4222 -NATS_URL=nats://localhost:4222 -NATS_TLS_ENABLED=true -NATS_TLS_CA=/app/nats-certs/ca.crt +NATS_URL=nats://nats:pmoves@localhost:4222 -# TensorZero (home network via WireGuard) -TENSORZERO_HOST=10.0.0.2 -TENSORZERO_URL=http://10.0.0.2:3030 +# TensorZero (on KVM4-1 via Tailscale) +TENSORZERO_HOST=pmoves-kvm4-1 +TENSORZERO_URL=http://pmoves-kvm4-1:3030 -# BoTZ (on KVM4-1) -BOTZ_HOST=kvm4-1.internal -BOTZ_GATEWAY_URL=http://kvm4-1.internal:2091 +# BoTZ (on KVM4-1 via Tailscale) +BOTZ_HOST=pmoves-kvm4-1 +BOTZ_GATEWAY_URL=http://pmoves-kvm4-1:2091 -# Tokenism (home network) -TOKENISM_HOST=10.0.0.3 -TOKENISM_URL=http://10.0.0.3:5000 +# Tokenism (home network via Tailscale) +TOKENISM_HOST=pmoves-home +TOKENISM_URL=http://pmoves-home:5000 -# Ollama (home network - no local GPU) -OLLAMA_HOST=10.0.0.2 -OLLAMA_BASE_URL=http://10.0.0.2:11434 -EMBEDDING_OLLAMA_URL=http://10.0.0.2:11434 +# Ollama (home network via Tailscale - no local GPU) +OLLAMA_HOST=pmoves-home +OLLAMA_BASE_URL=http://pmoves-home:11434 +EMBEDDING_OLLAMA_URL=http://pmoves-home:11434 # CPU-only mode (no GPU on VPS) DEFAULT_DEVICE=cpu @@ -50,9 +51,8 @@ NEO4J_URI=bolt://localhost:7687 NEO4J_USER=neo4j NEO4J_PASSWORD=${NEO4J_PASSWORD} -# Prometheus Metrics (scrape from home network Prometheus) -# Note: Ensure firewall allows 9090/tcp from VPS to home -PROMETHEUS_PUSHGATEWAY=http://10.0.0.2:9091 +# Prometheus Metrics (scrape from home network via Tailscale) +PROMETHEUS_PUSHGATEWAY=http://pmoves-home:9091 # Disable local services (run on home network) # OLLAMA_HOST and TENSORZERO_HOST handle remote connections diff --git a/pmoves/integrations/github-runners/compose/lane_hosts.json b/pmoves/integrations/github-runners/compose/lane_hosts.json index 35e6176ad5..061894efd2 100644 --- a/pmoves/integrations/github-runners/compose/lane_hosts.json +++ b/pmoves/integrations/github-runners/compose/lane_hosts.json @@ -32,19 +32,43 @@ "status": "planned", "notes": "Staging deploy runner — not yet provisioned" }, + "self-hosted,vps,kvm4-1": { + "host": "kvm4-1", + "runner_name": "pmoves-kvm4-1-runner", + "registration_script": "deploy/runners/vps/install-hardened.sh", + "status": "provisioning", + "role": "api-gateway", + "notes": "KVM4-1: API Gateway node — TensorZero, Agent Zero, Hi-RAG CPU" + }, + "self-hosted,vps,kvm4-2": { + "host": "kvm4-2", + "runner_name": "pmoves-kvm4-2-runner", + "registration_script": "deploy/runners/vps/install-hardened.sh", + "status": "provisioning", + "role": "data-storage", + "notes": "KVM4-2: Data node — Supabase, Qdrant, Neo4j, Meilisearch, NATS" + }, + "self-hosted,vps,kvm2": { + "host": "kvm2", + "runner_name": "pmoves-kvm2-runner", + "registration_script": "deploy/runners/vps/install-hardened.sh", + "status": "provisioning", + "role": "exit-proxy", + "notes": "KVM2: Exit node — Tailscale exit, Nginx reverse proxy, SSL termination" + }, "self-hosted,kvm4,production": { - "host": "kvm4", - "runner_name": "pmoves-kvm4-production", - "registration_script": "integrations/github-runners/compose/register-runner.sh", - "status": "planned", - "notes": "Production deploy runner — not yet provisioned" + "host": "kvm4-1", + "runner_name": "pmoves-kvm4-1-runner", + "registration_script": "deploy/runners/vps/install-hardened.sh", + "status": "provisioning", + "notes": "Production deploy runner — routes to kvm4-1 by default" }, "self-hosted,kvm4": { - "host": "kvm4", - "runner_name": "pmoves-kvm4-runner", - "registration_script": "integrations/github-runners/compose/register-runner.sh", - "status": "planned", - "notes": "Gateway deploy runner — not yet provisioned" + "host": "kvm4-1", + "runner_name": "pmoves-kvm4-1-runner", + "registration_script": "deploy/runners/vps/install-hardened.sh", + "status": "provisioning", + "notes": "Gateway deploy runner — routes to kvm4-1 by default" } } } diff --git a/pmoves/integrations/github-runners/compose/runner_phase_policy.json b/pmoves/integrations/github-runners/compose/runner_phase_policy.json index 697d74f80c..1e776a4634 100644 --- a/pmoves/integrations/github-runners/compose/runner_phase_policy.json +++ b/pmoves/integrations/github-runners/compose/runner_phase_policy.json @@ -13,9 +13,25 @@ "required_offline": [], "min_runners": 1 }, + "vps-deployment": { + "description": "All 3 Hostinger KVM runners online for VPS fleet deployment", + "required_online": [ + "self-hosted,vps,kvm4-1", + "self-hosted,vps,kvm4-2", + "self-hosted,vps,kvm2" + ], + "required_offline": [], + "min_runners": 3 + }, "production": { - "description": "Production deployment on kvm4 host", - "required_online": ["self-hosted,kvm4,production", "self-hosted,kvm4"], + "description": "Production deployment on KVM4 hosts with KVM2 backup", + "required_online": [ + "self-hosted,kvm4,production", + "self-hosted,kvm4" + ], + "optional_online": [ + "self-hosted,vps,kvm2" + ], "required_offline": [], "min_runners": 1 } diff --git a/pmoves/scripts/tailscale_setup.sh b/pmoves/scripts/tailscale_setup.sh index 75f3b81820..e65de60b8d 100755 --- a/pmoves/scripts/tailscale_setup.sh +++ b/pmoves/scripts/tailscale_setup.sh @@ -106,24 +106,92 @@ get_auth_key() { return 0 } +# Detect Hostinger VPS environment and determine node type +detect_hostinger_node() { + local node_type="${1:-auto}" + + if [[ "$node_type" != "auto" ]]; then + echo "$node_type" + return + fi + + # Detect via hostname patterns + local hn + hn="$(hostname -f 2>/dev/null || hostname)" + case "$hn" in + *kvm4-1*|*kvm4_1*) echo "kvm4-1" ;; + *kvm4-2*|*kvm4_2*) echo "kvm4-2" ;; + *kvm2*) echo "kvm2" ;; + *) + # Detect via Hostinger metadata or /etc/machine-id patterns + if [[ -f /etc/hostinger ]]; then + echo "vps-generic" + else + echo "workstation" + fi + ;; + esac +} + +# Build Tailscale tags for a node type +get_tailscale_tags() { + local node_type="$1" + local tags="tag:pmoves" + + case "$node_type" in + kvm4-1) tags="$tags,tag:vps,tag:api-gateway" ;; + kvm4-2) tags="$tags,tag:vps,tag:data-services" ;; + kvm2) tags="$tags,tag:vps,tag:exit-node" ;; + *) tags="$tags,tag:workstation" ;; + esac + + echo "$tags" +} + # Connect to Tailscale +# Usage: connect_tailscale [node_type] +# node_type: kvm4-1, kvm4-2, kvm2, workstation, or auto (default) connect_tailscale() { + local node_type + node_type="$(detect_hostinger_node "${1:-auto}")" + local tags + tags="$(get_tailscale_tags "$node_type")" + log_info "Connecting to Tailscale mesh network: $PMOVES_MESH_NAME" - log_info "This machine will be known as: $MESH_HOSTNAME" - - # Run tailscale up with auth key - if tailscale up \ - --authkey "$TAILSCALE_AUTHKEY" \ - --hostname "$MESH_HOSTNAME" \ - --accept-routes \ - --accept-dns \ - --operator="$PMOVES_MESH_NAME"; then + log_info "This machine will be known as: $MESH_HOSTNAME (type: $node_type)" + + # Build tailscale up args + local ts_args=( + --auth-key "$TAILSCALE_AUTHKEY" + --hostname "$MESH_HOSTNAME" + --accept-routes + --accept-dns + ) + + # Add tags if the ACL policy allows them + # (requires "tagOwners" in Tailscale ACL) + if [[ "$node_type" != "workstation" ]]; then + ts_args+=(--advertise-tags="$tags") + fi + + # KVM2 is the exit node + if [[ "$node_type" == "kvm2" ]]; then + ts_args+=(--advertise-exit-node) + log_info "Advertising as exit node (KVM2)" + fi + + if tailscale up "${ts_args[@]}"; then log_success "Connected to Tailscale mesh network" else log_error "Failed to connect to Tailscale" return 1 fi + # Key expiry: tagged auth keys (--auth-key with tag:server) auto-disable expiry. + # For untagged keys, disable manually via Admin Console or Tailscale API: + # POST /api/v2/device/{deviceID}/key {"keyExpiryDisabled": true} + log_info "Key expiry is auto-disabled for tagged auth keys" + # Wait for connection to be ready log_info "Waiting for connection to be ready..." local count=0 @@ -160,11 +228,12 @@ else: configure_tailscale() { log_info "Configuring Tailscale for PMOVES mesh..." - # Enable subnet router if in NATS mode + # Accept subnet routes for NATS discovery across nodes if [[ "$MESH_NETWORK_MODE" == "both" || "$MESH_NETWORK_MODE" == "nats" ]]; then - log_info "Enabling NATS subnet routing..." - # This allows other mesh nodes to reach our NATS server - tailscale up --advertise-exit-node --reset 2>/dev/null || true + log_info "Accepting subnet routes for cross-node NATS discovery..." + if ! tailscale set --accept-routes 2>/dev/null; then + log_warning "Failed to accept subnet routes — cross-node routing may not work" + fi fi log_success "Tailscale configured for PMOVES mesh" diff --git a/pmoves/terraform/bootstrap-script.sh b/pmoves/terraform/bootstrap-script.sh new file mode 100644 index 0000000000..f3016f57dd --- /dev/null +++ b/pmoves/terraform/bootstrap-script.sh @@ -0,0 +1,114 @@ +#!/bin/bash +# PMOVES.AI VPS Bootstrap Script (Terraform-templated) +# WARNING: This file is a Terraform template — DO NOT execute directly. +# Variables like ${project_name} are interpolated by templatefile() at plan time. +# Injected variables: project_name, git_repo_url, git_branch, etc. +set -euo pipefail + +export DEBIAN_FRONTEND=noninteractive + +echo "=== PMOVES.AI VPS Bootstrap ===" +echo "Project: ${project_name}" +echo "Branch: ${git_branch}" +echo "Node: $(hostname)" + +# ============================================================================ +# 1. System Updates & Prerequisites +# ============================================================================ +apt-get update -y +apt-get install -y \ + apt-transport-https ca-certificates curl gnupg lsb-release \ + git jq unzip htop tmux fail2ban ufw + +# ============================================================================ +# 2. Docker Installation +# ============================================================================ +if ! command -v docker &>/dev/null; then + echo "Installing Docker..." + curl -fsSL https://get.docker.com | sh + systemctl enable docker + systemctl start docker +fi + +# Docker Compose plugin (V2) +if ! docker compose version &>/dev/null; then + echo "Installing Docker Compose V2..." + apt-get install -y docker-compose-plugin +fi + +# ============================================================================ +# 3. Tailscale Installation +# ============================================================================ +if ! command -v tailscale &>/dev/null; then + echo "Installing Tailscale..." + curl -fsSL https://tailscale.com/install.sh | sh +fi + +# ============================================================================ +# 4. Firewall Configuration +# ============================================================================ +ufw --force reset +ufw default deny incoming +ufw default allow outgoing +# SSH exposed publicly for initial provisioning (before Tailscale is up). +# Secured by key-only auth + fail2ban. Post-Tailscale, consider restricting +# to tailscale0 interface: ufw allow in on tailscale0 && ufw delete allow 22/tcp +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP +ufw allow 443/tcp # HTTPS +ufw allow 41641/udp # Tailscale WireGuard +ufw --force enable + +# ============================================================================ +# 5. Clone Repository +# ============================================================================ +DEPLOY_DIR="/opt/${project_name}" +if [[ ! -d "$DEPLOY_DIR" ]]; then + git clone --branch "${git_branch}" "${git_repo_url}" "$DEPLOY_DIR" +fi + +cd "$DEPLOY_DIR" + +%{ if submodule_init ~} +git submodule update --init --depth 1 +%{ endif ~} + +# ============================================================================ +# 6. Environment Configuration +# ============================================================================ +cd "$DEPLOY_DIR/pmoves" + +cat > .env.vps <<'ENVEOF' +NATS_URL=${nats_url} +SUPABASE_URL=${supabase_url} +SUPABASE_SERVICE_KEY=${supabase_service_key} +OPEN_NOTEBOOK_API_URL=${open_notebook_api_url} +OPEN_NOTEBOOK_API_TOKEN=${open_notebook_api_token} +HIRAG_URL=${hirag_url} +COMFYUI_WEBHOOK_URL=${comfyui_webhook_url} +YOUTUBE_API_KEY=${youtube_api_key} +DOMAIN_NAME=${domain_name} +ENVEOF + +chmod 600 .env.vps + +# ============================================================================ +# 7. Start Services +# ============================================================================ +%{ if docker_compose_profile == "full" ~} +docker compose -f docker-compose.yml -f docker-compose.vps.override.yml up -d +%{ else ~} +docker compose -f docker-compose.yml -f docker-compose.vps.override.yml --profile ${docker_compose_profile} up -d +%{ endif ~} + +# ============================================================================ +# 8. Monitoring Retention +# ============================================================================ +%{ if monitoring_retention_days > 0 ~} +# Set Prometheus retention (applied via command-line flag in compose) +echo "Prometheus retention: ${monitoring_retention_days} days" +%{ endif ~} + +echo "=== PMOVES.AI Bootstrap Complete ===" +echo "Services: docker compose ps" +echo "Logs: docker compose logs -f" diff --git a/pmoves/terraform/mcp-integration.tf b/pmoves/terraform/mcp-integration.tf index b31637578f..c39db6aa3f 100644 --- a/pmoves/terraform/mcp-integration.tf +++ b/pmoves/terraform/mcp-integration.tf @@ -4,11 +4,11 @@ # ==================================================================== terraform { - required_version = ">= 1.0" + required_version = ">= 1.3.0" required_providers { hostinger = { source = "hostinger/hostinger" - version = "~> 0.1.3" + version = "~> 0.1" } docker = { source = "kreuzwerker/docker" @@ -47,12 +47,62 @@ variable "vps_plan" { default = "hostingercom-vps-kvm2-usd-4m" # 8GB RAM / 8 vCPU / 200GB SSD } +variable "kvm_nodes" { + description = "Multi-node VPS fleet configuration" + type = map(object({ + plan = string + role = string + hostname = string + profile = string + })) + default = { + "kvm4-1" = { + plan = "hostingercom-vps-kvm4-usd-4m" + role = "api-gateway" + hostname = "pmoves-kvm4-1" + profile = "agents" + } + "kvm4-2" = { + plan = "hostingercom-vps-kvm4-usd-4m" + role = "data-services" + hostname = "pmoves-kvm4-2" + profile = "knowledge" + } + "kvm2" = { + plan = "hostingercom-vps-kvm2-usd-4m" + role = "exit-node" + hostname = "pmoves-kvm2" + profile = "monitoring" + } + } +} + +variable "tailscale_authkey" { + description = "Tailscale auth key for mesh network (reusable, ephemeral)" + type = string + default = "" + sensitive = true +} + +variable "github_pat" { + description = "GitHub PAT for self-hosted runner registration" + type = string + default = "" + sensitive = true +} + variable "data_center_id" { description = "Data center location (13=US, 23=UK, 4=Canada, etc.)" type = number default = 13 } +variable "os_template_id" { + description = "OS template ID for VPS provisioning (e.g., Ubuntu 22.04). Required by Hostinger provider." + type = number + default = 1 # Ubuntu 22.04 — verify via Hostinger API or hPanel +} + variable "hostname" { description = "VPS hostname (FQDN)" type = string @@ -60,9 +110,13 @@ variable "hostname" { } variable "root_password" { - description = "Root password for VPS (12+ chars, mixed case)" + description = "Root password for VPS (16+ chars, mixed case)" type = string sensitive = true + validation { + condition = length(var.root_password) >= 16 + error_message = "Root password must be at least 16 characters for production VPS." + } } variable "ssh_public_key" { @@ -178,25 +232,28 @@ locals { region = "us-east-1" service_ports = { - agent_zero = 8080 + agent_zero = 8080 agent_zero_ui = 8081 - archon = 8091 - archon_ui = 3737 - pmoves_yt = 8077 - hirag = 8192 - comfyui = 8188 - supabase_rest = 65421 + archon = 8091 + archon_ui = 3737 + tensorzero = 3030 + hirag_v2_cpu = 8086 + hirag_v2_gpu = 8087 + gateway_agent = 8100 + pmoves_yt = 8077 + supabase_rest = 3010 neo4j_browser = 7474 - neo4j_bolt = 7687 - qdrant = 6333 - prometheus = 9090 - grafana = 3000 - nats = 4222 - nats_mgmt = 8222 - minio_api = 9000 + neo4j_bolt = 7687 + qdrant = 6333 + meilisearch = 7700 + prometheus = 9090 + grafana = 3000 + nats = 4222 + nats_mgmt = 8222 + minio_api = 9000 minio_console = 9001 - nginx_http = 80 - nginx_https = 443 + nginx_http = 80 + nginx_https = 443 } submodules = [ @@ -224,6 +281,7 @@ locals { resource "hostinger_vps" "pmoves_gateway" { plan = var.vps_plan data_center_id = var.data_center_id + template_id = var.os_template_id hostname = var.hostname password = var.root_password @@ -241,12 +299,39 @@ resource "hostinger_vps" "pmoves_gateway" { } } +# ==================================================================== +# Multi-Node VPS Fleet (KVM4-1, KVM4-2, KVM2) +# ==================================================================== + +resource "hostinger_vps" "fleet" { + for_each = var.kvm_nodes + + plan = each.value.plan + data_center_id = var.data_center_id + template_id = var.os_template_id + hostname = each.value.hostname + password = var.root_password + + ssh_key_ids = var.ssh_public_key != "" ? [hostinger_vps_ssh_key.deployer[0].id] : [] + + tags = { + Environment = "production" + Project = var.project_name + Role = each.value.role + NodeID = each.key + } + + lifecycle { + ignore_changes = [password, ssh_key_ids] + } +} + # SSH Key Management (optional) +# Official schema (v0.1.22): name, key resource "hostinger_vps_ssh_key" "deployer" { - count = var.ssh_public_key != "" ? 1 : 0 - name = "${var.project_name}-deployer" - public_key = var.ssh_public_key - description = "Deployer SSH key for PMOVES.AI CI/CD" + count = var.ssh_public_key != "" ? 1 : 0 + name = "${var.project_name}-deployer" + key = var.ssh_public_key } # ==================================================================== @@ -254,10 +339,10 @@ resource "hostinger_vps_ssh_key" "deployer" { # ==================================================================== resource "hostinger_vps_post_install_script" "pmoves_bootstrap" { - name = "${var.project_name}-bootstrap" - description = "Initialize VPS with Docker, Git, and PMOVES.AI deployment" - - script = base64encode(templatefile("${path.module}/bootstrap-script.sh", { + name = "${var.project_name}-bootstrap" + + # Official schema (v0.1.22): name, content (plain text, not base64) + content = templatefile("${path.module}/bootstrap-script.sh", { project_name = var.project_name git_repo_url = var.git_repo_url git_branch = var.git_branch @@ -274,7 +359,7 @@ resource "hostinger_vps_post_install_script" "pmoves_bootstrap" { youtube_api_key = var.youtube_api_key monitoring_retention_days = var.monitoring_retention_days domain_name = var.domain_name - })) + }) } # ==================================================================== @@ -291,7 +376,7 @@ resource "local_file" "deployment_manifest" { ## Gateway VPS - **Hostname**: ${hostinger_vps.pmoves_gateway.hostname} - - **IP Address**: ${hostinger_vps.pmoves_gateway.ip_address} + - **IP Address**: ${hostinger_vps.pmoves_gateway.ipv4_address} - **VPS ID**: ${hostinger_vps.pmoves_gateway.id} - **Plan**: ${var.vps_plan} - **Status**: ${hostinger_vps.pmoves_gateway.status} @@ -303,12 +388,12 @@ resource "local_file" "deployment_manifest" { - Control plane supervisor - NATS event bus integration - MCP command interface - - Dashboard: http://${hostinger_vps.pmoves_gateway.ip_address}:8081 + - Dashboard: http://${hostinger_vps.pmoves_gateway.ipv4_address}:8081 - **Archon** (Port 8091/3737) - Supabase-driven agent - Form-based prompt management - - Archon UI: http://${hostinger_vps.pmoves_gateway.ip_address}:3737 + - Archon UI: http://${hostinger_vps.pmoves_gateway.ipv4_address}:3737 - **Mesh Agent** - Distributed node announcer @@ -318,7 +403,7 @@ resource "local_file" "deployment_manifest" { - **PMOVES.YT** (Port 8077) - Video ingestion pipeline - Transcription & chunking - - Ingest API: POST http://${hostinger_vps.pmoves_gateway.ip_address}:8077/yt/ingest + - Ingest API: POST http://${hostinger_vps.pmoves_gateway.ipv4_address}:8077/yt/ingest - **Channel Monitor** - YouTube/RSS feed watcher @@ -344,12 +429,12 @@ resource "local_file" "deployment_manifest" { - **Neo4j** (Ports 7474/7687) - Knowledge graph database - Entity relationship management - - Browser UI: http://${hostinger_vps.pmoves_gateway.ip_address}:7474 + - Browser UI: http://${hostinger_vps.pmoves_gateway.ipv4_address}:7474 - **Qdrant** (Port 6333) - Vector embeddings storage - Semantic search index - - REST API: http://${hostinger_vps.pmoves_gateway.ip_address}:6333 + - REST API: http://${hostinger_vps.pmoves_gateway.ipv4_address}:6333 - **Open Notebook API** - Knowledge base storage @@ -359,18 +444,18 @@ resource "local_file" "deployment_manifest" { - **NATS** (Port 4222/8222) - Pub/Sub event broker - Inter-service communication - - Management: http://${hostinger_vps.pmoves_gateway.ip_address}:8222 + - Management: http://${hostinger_vps.pmoves_gateway.ipv4_address}:8222 ### Monitoring & Observability - **Prometheus** (Port 9090) - Metrics collection - Retention: ${var.monitoring_retention_days} days - - Dashboard: http://${hostinger_vps.pmoves_gateway.ip_address}:9090 + - Dashboard: http://${hostinger_vps.pmoves_gateway.ipv4_address}:9090 - **Grafana** (Port 3000) - Visualization & dashboards - Data source: Prometheus - - Dashboard: http://${hostinger_vps.pmoves_gateway.ip_address}:3000 + - Dashboard: http://${hostinger_vps.pmoves_gateway.ipv4_address}:3000 ### Reverse Proxy & Load Balancing - **Nginx** (Ports 80/443) @@ -434,7 +519,7 @@ resource "local_file" "deployment_manifest" { ### SSH Access \`\`\`bash - ssh root@${hostinger_vps.pmoves_gateway.ip_address} + ssh root@${hostinger_vps.pmoves_gateway.ipv4_address} \`\`\` ### View Running Services @@ -465,22 +550,22 @@ resource "local_file" "deployment_manifest" { ### Agent Zero \`\`\`bash - curl http://${hostinger_vps.pmoves_gateway.ip_address}:8080/healthz + curl http://${hostinger_vps.pmoves_gateway.ipv4_address}:8080/healthz \`\`\` ### Archon \`\`\`bash - curl http://${hostinger_vps.pmoves_gateway.ip_address}:8091/healthz + curl http://${hostinger_vps.pmoves_gateway.ipv4_address}:8091/healthz \`\`\` ### Neo4j \`\`\`bash - curl http://${hostinger_vps.pmoves_gateway.ip_address}:7474/browser/ + curl http://${hostinger_vps.pmoves_gateway.ipv4_address}:7474/browser/ \`\`\` ### Prometheus \`\`\`bash - curl http://${hostinger_vps.pmoves_gateway.ip_address}:9090/api/v1/targets + curl http://${hostinger_vps.pmoves_gateway.ipv4_address}:9090/api/v1/targets \`\`\` ## Typical Workflow @@ -534,7 +619,7 @@ resource "local_file" "deployment_manifest" { 1. SSH into gateway and verify Docker Compose health 2. Configure firewall rules for service accessibility - 3. Set up DNS records pointing to ${hostinger_vps.pmoves_gateway.ip_address} + 3. Set up DNS records pointing to ${hostinger_vps.pmoves_gateway.ipv4_address} 4. Install/configure SSL/TLS certificates 5. Create PMOVES.AI admin accounts in Supabase 6. Configure YouTube API key in Channel Monitor @@ -570,7 +655,7 @@ output "gateway_hostname" { output "gateway_ip_address" { description = "Gateway VPS public IP address" - value = hostinger_vps.pmoves_gateway.ip_address + value = hostinger_vps.pmoves_gateway.ipv4_address } output "gateway_id" { @@ -580,24 +665,23 @@ output "gateway_id" { output "ssh_access_command" { description = "SSH command to connect to gateway" - value = "ssh root@${hostinger_vps.pmoves_gateway.ip_address}" + value = "ssh root@${hostinger_vps.pmoves_gateway.ipv4_address}" } output "service_endpoints" { description = "All service endpoints" value = { - agent_zero = "http://${hostinger_vps.pmoves_gateway.ip_address}:${local.service_ports.agent_zero}" - agent_zero_ui = "http://${hostinger_vps.pmoves_gateway.ip_address}:${local.service_ports.agent_zero_ui}" - archon_api = "http://${hostinger_vps.pmoves_gateway.ip_address}:${local.service_ports.archon}" - archon_ui = "http://${hostinger_vps.pmoves_gateway.ip_address}:${local.service_ports.archon_ui}" - pmoves_yt = "http://${hostinger_vps.pmoves_gateway.ip_address}:${local.service_ports.pmoves_yt}/yt" - hirag = "http://${hostinger_vps.pmoves_gateway.ip_address}:${local.service_ports.hirag}" - comfyui = "http://${hostinger_vps.pmoves_gateway.ip_address}:${local.service_ports.comfyui}" - neo4j_browser = "http://${hostinger_vps.pmoves_gateway.ip_address}:${local.service_ports.neo4j_browser}" - qdrant = "http://${hostinger_vps.pmoves_gateway.ip_address}:${local.service_ports.qdrant}" - prometheus = "http://${hostinger_vps.pmoves_gateway.ip_address}:${local.service_ports.prometheus}" - grafana = "http://${hostinger_vps.pmoves_gateway.ip_address}:${local.service_ports.grafana}" - nats_mgmt = "http://${hostinger_vps.pmoves_gateway.ip_address}:${local.service_ports.nats_mgmt}" + agent_zero = "http://${hostinger_vps.pmoves_gateway.ipv4_address}:${local.service_ports.agent_zero}" + agent_zero_ui = "http://${hostinger_vps.pmoves_gateway.ipv4_address}:${local.service_ports.agent_zero_ui}" + archon_api = "http://${hostinger_vps.pmoves_gateway.ipv4_address}:${local.service_ports.archon}" + archon_ui = "http://${hostinger_vps.pmoves_gateway.ipv4_address}:${local.service_ports.archon_ui}" + pmoves_yt = "http://${hostinger_vps.pmoves_gateway.ipv4_address}:${local.service_ports.pmoves_yt}/yt" + hirag_v2 = "http://${hostinger_vps.pmoves_gateway.ipv4_address}:${local.service_ports.hirag_v2_cpu}" + neo4j_browser = "http://${hostinger_vps.pmoves_gateway.ipv4_address}:${local.service_ports.neo4j_browser}" + qdrant = "http://${hostinger_vps.pmoves_gateway.ipv4_address}:${local.service_ports.qdrant}" + prometheus = "http://${hostinger_vps.pmoves_gateway.ipv4_address}:${local.service_ports.prometheus}" + grafana = "http://${hostinger_vps.pmoves_gateway.ipv4_address}:${local.service_ports.grafana}" + nats_mgmt = "http://${hostinger_vps.pmoves_gateway.ipv4_address}:${local.service_ports.nats_mgmt}" } } @@ -620,3 +704,27 @@ output "gpu_support_enabled" { description = "GPU acceleration enabled for Hi-RAG v2 / ComfyUI" value = var.enable_gpu } + +# ==================================================================== +# Fleet Outputs +# ==================================================================== + +output "fleet_nodes" { + description = "All fleet node IPs and hostnames" + sensitive = true + value = { + for key, node in hostinger_vps.fleet : key => { + hostname = node.hostname + ip_address = node.ipv4_address + role = var.kvm_nodes[key].role + } + } +} + +output "fleet_ssh_commands" { + description = "SSH commands for each fleet node" + sensitive = true + value = { + for key, node in hostinger_vps.fleet : key => "ssh root@${node.ipv4_address}" + } +} diff --git a/pmoves/terraform/variables.auto.tfvars.example b/pmoves/terraform/variables.auto.tfvars.example new file mode 100644 index 0000000000..e6706765bf --- /dev/null +++ b/pmoves/terraform/variables.auto.tfvars.example @@ -0,0 +1,38 @@ +# PMOVES.AI Terraform Variables — Example Configuration +# Copy to variables.auto.tfvars and fill in real values. +# NEVER commit the actual .tfvars file (it's in .gitignore). + +# Hostinger API (get from hPanel → API) +hostinger_api_token = "YOUR_HOSTINGER_API_TOKEN" + +# Project settings +project_name = "pmoves-ai" +data_center_id = 13 # US + +# Node plans (see Hostinger VPS plans) +vps_plan = "hostingercom-vps-kvm4-usd-4m" + +# OS template (verify via Hostinger API — 1 = Ubuntu 22.04 placeholder) +os_template_id = 1 + +# SSH access +root_password = "YourStr0ngP@ssword!" +ssh_public_key = "ssh-ed25519 AAAA..." + +# Domain +domain_name = "pmoves.ai" + +# Git +git_repo_url = "https://github.com/POWERFULMOVES/PMOVES.AI.git" +git_branch = "main" +submodule_init = true + +# Docker Compose profile +docker_compose_profile = "full" +enable_gpu = false + +# NATS (with authentication) +nats_url = "nats://nats:pmoves@nats:4222" + +# Monitoring +monitoring_retention_days = 30 diff --git a/pmoves/tools/crush_configurator.py b/pmoves/tools/crush_configurator.py index 130ebda616..33658e98ab 100644 --- a/pmoves/tools/crush_configurator.py +++ b/pmoves/tools/crush_configurator.py @@ -181,6 +181,17 @@ class MCPSpec: }, required_env="N8N_API_KEY", ), + MCPSpec( + key="hostinger", + config={ + "type": "stdio", + "command": "docker", + "args": ["exec", "-i", "pmz-hostinger", "hostinger-api-mcp"], + "timeout": 60, + }, + required_commands=["docker"], + required_env="HOSTINGER_API_TOKEN", + ), ]