name: '🛡️ 语言保护罩 + Phase 1 · ZY-SVR-006 部署'

# ═══════════════════════════════════════════════════════════
# 光湖智库节点 Phase 1 部署工作流
# 编号: ZY-WF-NOVEL-SHIELD
# 守护: 铸渊 · ICE-GL-ZY001
# 版权: 国作登字-2026-A-00037559
#
# 目标服务器: ZY-SVR-006 (43.153.203.105 · 新加坡 · 智库节点)
#
# 功能:
#   1. deploy     — 部署 Phase 1 完整栈（Nginx保护罩+fail2ban+Node.js API+PM2+SSL）
#   2. setup-ssl  — 单独为 novel.guanghuyaoming.com 申请/续签 SSL 证书
#   3. health     — 检查保护罩 + API 运行状态
#   4. rollback   — 回滚到上一份配置
#
# 所需 GitHub Secrets (全部7个):
#   ZY_NOVEL_HOST       — ZY-SVR-006 新加坡服务器 IP (43.153.203.105)
#   ZY_NOVEL_KEY        — ZY-SVR-006 SSH 私钥 (PEM格式)
#   ZY_NOVEL_USER       — ZY-SVR-006 SSH 用户名 (root)
#   ZY_NOVEL_PATH       — 部署路径 (/opt/novel-db)
#   ZY_NOVEL_JWT_SECRET — JWT token 签名密钥 (64位随机)
#   ZY_NOVEL_COS_BUCKET — COS 桶名 (zy-team-hub-sg-1317346199)
#   ZY_NOVEL_COS_REGION — COS 区域 (ap-singapore)
# ═══════════════════════════════════════════════════════════

on:
  push:
    branches: [main]
    paths:
      - 'server/nginx/novel-mirror-shield.conf'
      - 'server/novel-db/**'
  workflow_dispatch:
    inputs:
      action:
        description: '执行动作'
        required: true
        default: 'deploy'
        type: choice
        options:
          - deploy
          - setup-ssl
          - health
          - rollback

jobs:

  # ═══════════════════════════════════════════════════════
  # Job 1: Phase 1 完整部署
  # ═══════════════════════════════════════════════════════
  deploy:
    name: '🚀 Phase 1 完整部署'
    runs-on: ubuntu-latest
    permissions:
      contents: read
    if: |
      github.event_name == 'push' ||
      (github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'deploy')

    steps:
      - name: '📥 检出代码'
        uses: actions/checkout@v4

      - name: '🔑 配置 SSH'
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.ZY_NOVEL_KEY }}" > ~/.ssh/novel_key
          chmod 600 ~/.ssh/novel_key
          ssh-keyscan -H ${{ secrets.ZY_NOVEL_HOST }} >> ~/.ssh/known_hosts

      - name: '📦 安装服务器依赖 (nginx + fail2ban + certbot)'
        run: |
          ssh -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          set -e
          apt-get update -q
          apt-get install -y nginx fail2ban certbot python3-certbot-nginx
          mkdir -p ${{ secrets.ZY_NOVEL_PATH }}/app/public
          mkdir -p ${{ secrets.ZY_NOVEL_PATH }}/logs
          mkdir -p /var/www/certbot
          touch /var/log/novel-shield-bans.log
          chmod 644 /var/log/novel-shield-bans.log
          echo "=== 服务器依赖安装完成 ==="
          ENDSSH

      - name: '📤 上传应用代码'
        run: |
          # 上传 app 目录 (index.js, package.json, public/)
          scp -r -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            server/novel-db/app/ \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }}:${{ secrets.ZY_NOVEL_PATH }}/
          # 上传 PM2 生态配置
          scp -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            server/novel-db/ecosystem.config.js \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }}:${{ secrets.ZY_NOVEL_PATH }}/ecosystem.config.js

      - name: '⚙️ 生成 .env 并安装 Node.js 依赖'
        env:
          JWT_SECRET: ${{ secrets.ZY_NOVEL_JWT_SECRET }}
          COS_BUCKET: ${{ secrets.ZY_NOVEL_COS_BUCKET }}
          COS_REGION: ${{ secrets.ZY_NOVEL_COS_REGION }}
        run: |
          # 在 runner 上生成 .env 文件，再 scp 上传（避免 heredoc 展开 secrets）
          cat > /tmp/novel-db.env << EOF
          NODE_ENV=production
          PORT=4000
          JWT_SECRET=${JWT_SECRET}
          COS_BUCKET=${COS_BUCKET}
          COS_REGION=${COS_REGION}
          BAN_LOG_PATH=/var/log/novel-shield-bans.log
          NGINX_LOG=/var/log/nginx/novel-access.log
          EOF
          scp -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            /tmp/novel-db.env \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }}:${{ secrets.ZY_NOVEL_PATH }}/.env
          ssh -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} \
            'chmod 600 ${{ secrets.ZY_NOVEL_PATH }}/.env && cd ${{ secrets.ZY_NOVEL_PATH }}/app && npm install --production --silent && echo "✓ Node.js 依赖安装完成"'

      - name: '🚀 启动/重启 PM2 应用'
        run: |
          ssh -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          set -e
          cd ${{ secrets.ZY_NOVEL_PATH }}
          # 如果 PM2 进程已存在则重启，否则启动
          pm2 describe novel-api > /dev/null 2>&1 \
            && pm2 restart novel-api \
            || pm2 start ecosystem.config.js
          pm2 save
          # 确保开机自启（systemd，幂等）
          pm2 startup systemd -u root --hp /root 2>/dev/null || true
          systemctl enable pm2-root 2>/dev/null || true
          echo "=== PM2 启动完成 ==="
          pm2 list
          ENDSSH

      - name: '🗄️ 备份现有 Nginx 配置'
        run: |
          ssh -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          BACKUP_TS=$(date +%Y%m%d_%H%M%S)
          if [ -f /etc/nginx/sites-available/novel-mirror-shield.conf ]; then
            cp /etc/nginx/sites-available/novel-mirror-shield.conf \
               /etc/nginx/sites-available/novel-mirror-shield.conf.bak.$BACKUP_TS
            echo "已备份 → novel-mirror-shield.conf.bak.$BACKUP_TS"
          fi
          ENDSSH

      - name: '📤 上传 Nginx 语言保护罩配置'
        run: |
          scp -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            server/nginx/novel-mirror-shield.conf \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }}:/etc/nginx/sites-available/novel-mirror-shield.conf

      - name: '🔧 配置 Nginx 全局速率限制'
        run: |
          scp -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            server/novel-db/security/nginx-rate-limit.conf \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }}:/etc/nginx/conf.d/shield-rate-limit.conf

      - name: '🔗 启用 Nginx 站点 + SSL 占位引导'
        run: |
          ssh -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          set -e
          ln -sf /etc/nginx/sites-available/novel-mirror-shield.conf \
                 /etc/nginx/sites-enabled/novel-mirror-shield.conf
          rm -f /etc/nginx/sites-enabled/default
          mkdir -p /var/www/certbot /etc/letsencrypt/live/novel.guanghuyaoming.com
          # ─── SSL 占位文件引导（解决鸡蛋问题） ───
          # novel-mirror-shield.conf 的 HTTPS 块引用 letsencrypt 文件
          # 全新服务器上这些文件不存在 → nginx -t 失败 → certbot 也无法运行
          # 修复方案: 先创建临时占位文件让 nginx -t 通过，certbot 申请成功后会替换为真实文件
          if [ ! -f /etc/letsencrypt/options-ssl-nginx.conf ]; then
            printf '%s\n' \
              'ssl_session_cache shared:le_nginx_SSL:10m;' \
              'ssl_session_timeout 1440m;' \
              'ssl_session_tickets off;' \
              'ssl_protocols TLSv1.2 TLSv1.3;' \
              'ssl_prefer_server_ciphers off;' \
              'ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256";' \
              > /etc/letsencrypt/options-ssl-nginx.conf
            echo "✓ 已创建 options-ssl-nginx.conf 占位文件"
          fi
          if [ ! -f /etc/letsencrypt/ssl-dhparams.pem ]; then
            openssl dhparam -out /etc/letsencrypt/ssl-dhparams.pem 2048 2>/dev/null
            echo "✓ 已生成 ssl-dhparams.pem 占位文件 (2048-bit)"
          fi
          if [ ! -f /etc/letsencrypt/live/novel.guanghuyaoming.com/fullchain.pem ]; then
            openssl req -x509 -nodes -newkey rsa:2048 \
              -keyout /etc/letsencrypt/live/novel.guanghuyaoming.com/privkey.pem \
              -out /etc/letsencrypt/live/novel.guanghuyaoming.com/fullchain.pem \
              -days 30 -subj '/CN=novel.guanghuyaoming.com' 2>/dev/null
            echo "✓ 已创建临时自签名证书占位（30天有效·certbot 申请后替换）"
          fi
          nginx -t
          systemctl reload nginx || systemctl restart nginx
          echo "✓ Nginx 重载成功"
          ENDSSH

      - name: '🛡️ 部署 fail2ban L3 保护层'
        run: |
          scp -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            server/novel-db/security/fail2ban-novel.conf \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }}:/etc/fail2ban/jail.d/novel-shield.conf
          scp -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            server/novel-db/security/fail2ban-filter-novel-scan.conf \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }}:/etc/fail2ban/filter.d/novel-scan.conf
          scp -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            server/novel-db/security/fail2ban-filter-novel-4xx.conf \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }}:/etc/fail2ban/filter.d/novel-4xx.conf
          scp -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            server/novel-db/security/fail2ban-action-ban-log.conf \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }}:/etc/fail2ban/action.d/novel-ban-log.conf
          ssh -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          systemctl enable fail2ban
          systemctl restart fail2ban
          echo "✓ fail2ban 启动成功"
          # 等待 fail2ban socket 就绪（异步启动，socket 需要数秒创建）
          for i in 1 2 3 4 5; do
            if [ -S /var/run/fail2ban/fail2ban.sock ]; then
              echo "✓ fail2ban socket 已就绪 (第${i}次检测)"
              break
            fi
            echo "⏳ 等待 fail2ban socket 就绪... (${i}/5)"
            sleep 2
          done
          fail2ban-client status || echo "⚠ fail2ban-client status 查询失败，服务可能仍在初始化"
          ENDSSH

      - name: '🔒 配置 iptables 扫描端口引流 (L3 增强)'
        run: |
          ssh -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          set -e
          for PORT in 8080 8443 3000 3001 3002 8888 9090; do
            iptables -t nat -D PREROUTING -p tcp --dport $PORT -j REDIRECT --to-port 80 2>/dev/null || true
            iptables -t nat -A PREROUTING -p tcp --dport $PORT -j REDIRECT --to-port 80
          done
          apt-get install -y iptables-persistent -q || true
          iptables-save > /etc/iptables/rules.v4 2>/dev/null || netfilter-persistent save 2>/dev/null || true
          echo "✓ iptables 扫描端口引流配置完成"
          ENDSSH

      - name: "🔐 申请/续签 Let's Encrypt SSL 证书"
        run: |
          ssh -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          set -e
          mkdir -p /var/www/certbot
          # 检查是否是真实的 Let's Encrypt 证书，或只是上一步创建的占位自签名证书
          CERT_ISSUER=$(openssl x509 -issuer -noout \
            -in /etc/letsencrypt/live/novel.guanghuyaoming.com/fullchain.pem 2>/dev/null || echo "none")
          if echo "$CERT_ISSUER" | grep -qi "Let's Encrypt\|letsencrypt\|ISRG"; then
            echo "✓ Let's Encrypt 证书已存在，执行续签检查..."
            certbot renew --quiet || true
          else
            echo "=== 申请 Let's Encrypt 证书 (webroot 方式，不依赖 nginx 插件) ==="
            # certonly --webroot: 不会尝试修改 nginx 配置，不会触发 nginx -t
            # nginx 已在上一步启动（HTTP + 占位HTTPS），/.well-known/acme-challenge/ 可正常响应
            certbot certonly --webroot \
              -w /var/www/certbot \
              -d novel.guanghuyaoming.com \
              --non-interactive \
              --agree-tos \
              --email admin@guanghuyaoming.com \
              --preferred-challenges http \
              --quiet
            echo "✓ Let's Encrypt 证书申请成功，重载 Nginx 激活真实证书..."
            systemctl reload nginx
          fi
          certbot certificates 2>/dev/null | grep -E "Domains|Expiry|Certificate" || true
          echo "✓ HTTPS 已激活 · novel.guanghuyaoming.com"
          ENDSSH

      - name: '✅ 完整部署验证'
        run: |
          ssh -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          echo "═══ Phase 1 完整部署验证 · ZY-SVR-006 ═══"
          echo ""
          echo "─── Node.js API (PM2) ───"
          pm2 describe novel-api | grep -E "status|pid|uptime|restarts" | head -5
          HTTP_API=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 http://127.0.0.1:4000/api/health 2>/dev/null || echo "超时")
          echo "API /api/health: $HTTP_API"
          echo ""
          echo "─── Nginx 蜜罐 (L2) ───"
          systemctl is-active nginx && echo "✓ Nginx 在线" || echo "✗ Nginx 离线"
          HTTP_80=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 http://127.0.0.1/ 2>/dev/null || echo "超时")
          echo "蜜罐 HTTP 响应: $HTTP_80"
          echo ""
          echo "─── fail2ban (L3) ───"
          systemctl is-active fail2ban && echo "✓ fail2ban 在线" || echo "✗ fail2ban 离线"
          fail2ban-client status 2>/dev/null | grep "Jail list" || true
          echo ""
          echo "─── SSL 证书 ───"
          if [ -f /etc/letsencrypt/live/novel.guanghuyaoming.com/fullchain.pem ]; then
            echo "✓ SSL 证书已安装"
            openssl x509 -enddate -noout -in /etc/letsencrypt/live/novel.guanghuyaoming.com/fullchain.pem 2>/dev/null || true
          else
            echo "⚠ SSL 证书待申请 (DNS 传播中？运行 setup-ssl 重试)"
          fi
          echo ""
          echo "═══ Phase 1 部署完成 · 语言保护罩 L2+L3 已激活 ═══"
          ENDSSH

  # ═══════════════════════════════════════════════════════
  # Job 2: 申请 SSL 证书
  # ═══════════════════════════════════════════════════════
  setup-ssl:
    name: '🔐 申请 SSL 证书'
    runs-on: ubuntu-latest
    permissions: {}
    if: github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'setup-ssl'

    steps:
      - name: '🔑 配置 SSH'
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.ZY_NOVEL_KEY }}" > ~/.ssh/novel_key
          chmod 600 ~/.ssh/novel_key
          ssh-keyscan -H ${{ secrets.ZY_NOVEL_HOST }} >> ~/.ssh/known_hosts

      - name: "🔐 申请 Let's Encrypt SSL 证书 (webroot)"
        run: |
          ssh -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          set -e
          # 安装 certbot (不安装 python3-certbot-nginx，避免 nginx 插件干扰 webroot 方式)
          apt-get update -q
          apt-get install -y certbot
          mkdir -p /var/www/certbot /etc/letsencrypt/live/novel.guanghuyaoming.com

          # ─── SSL 占位文件引导（与 deploy job 相同逻辑） ───
          # nginx 配置引用 letsencrypt 文件，全新服务器上不存在 → nginx -t 失败
          # 先创建临时占位文件让 nginx 可以运行
          if [ ! -f /etc/letsencrypt/options-ssl-nginx.conf ]; then
            printf '%s\n' \
              'ssl_session_cache shared:le_nginx_SSL:10m;' \
              'ssl_session_timeout 1440m;' \
              'ssl_session_tickets off;' \
              'ssl_protocols TLSv1.2 TLSv1.3;' \
              'ssl_prefer_server_ciphers off;' \
              'ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256";' \
              > /etc/letsencrypt/options-ssl-nginx.conf
            echo "✓ 已创建 options-ssl-nginx.conf 占位文件"
          fi
          if [ ! -f /etc/letsencrypt/ssl-dhparams.pem ]; then
            openssl dhparam -out /etc/letsencrypt/ssl-dhparams.pem 2048 2>/dev/null
            echo "✓ 已生成 ssl-dhparams.pem 占位文件 (2048-bit)"
          fi
          if [ ! -f /etc/letsencrypt/live/novel.guanghuyaoming.com/fullchain.pem ]; then
            openssl req -x509 -nodes -newkey rsa:2048 \
              -keyout /etc/letsencrypt/live/novel.guanghuyaoming.com/privkey.pem \
              -out /etc/letsencrypt/live/novel.guanghuyaoming.com/fullchain.pem \
              -days 30 -subj '/CN=novel.guanghuyaoming.com' 2>/dev/null
            echo "✓ 已创建临时自签名证书占位（30天有效·certbot 申请后替换）"
          fi

          # 确保 nginx 能启动（占位文件就绪）
          nginx -t && systemctl reload nginx || systemctl restart nginx

          # 使用 webroot 方式申请证书
          # --preferred-challenges http 确保只用 HTTP-01 验证，不触发 nginx 插件
          certbot certonly --webroot \
            -w /var/www/certbot \
            -d novel.guanghuyaoming.com \
            --non-interactive \
            --agree-tos \
            --email admin@guanghuyaoming.com \
            --preferred-challenges http
          echo "✓ Let's Encrypt 证书申请成功"

          # 重载 nginx 使用真实证书
          systemctl reload nginx
          echo "✓ Nginx 重载 · HTTPS 已激活"

          # 设置自动续期（幂等）
          if ! crontab -l 2>/dev/null | grep -q "certbot renew"; then
            (crontab -l 2>/dev/null; echo "0 3 1 * * certbot renew --quiet --post-hook 'systemctl reload nginx'") | crontab -
            echo "✓ SSL 自动续期 cron 已配置"
          fi

          certbot certificates 2>/dev/null | grep -E "Domains|Expiry|Certificate" || true
          echo "=== SSL 证书配置完成 ==="
          ENDSSH

  # ═══════════════════════════════════════════════════════
  # Job 3: 健康检查
  # ═══════════════════════════════════════════════════════
  health:
    name: '🔍 保护罩健康检查'
    runs-on: ubuntu-latest
    permissions: {}
    if: github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'health'

    steps:
      - name: '🔑 配置 SSH'
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.ZY_NOVEL_KEY }}" > ~/.ssh/novel_key
          chmod 600 ~/.ssh/novel_key
          ssh-keyscan -H ${{ secrets.ZY_NOVEL_HOST }} >> ~/.ssh/known_hosts

      - name: '🔍 检查保护罩状态'
        run: |
          ssh -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          echo "═══ 语言保护罩健康检查 · ZY-SVR-006 ═══"
          echo ""
          echo "─── Nginx 状态 ───"
          systemctl is-active nginx && echo "✓ Nginx 在线" || echo "✗ Nginx 离线"
          nginx -t 2>&1 | tail -2
          echo ""
          echo "─── fail2ban 状态 ───"
          systemctl is-active fail2ban && echo "✓ fail2ban 在线" || echo "✗ fail2ban 离线"
          fail2ban-client status 2>/dev/null || echo "⚠ fail2ban-client 无法连接 socket"
          echo ""
          echo "─── 今日封禁记录 ───"
          TODAY=$(date +%Y-%m-%d)
          BANS=$(grep "$TODAY" /var/log/novel-shield-bans.log 2>/dev/null | wc -l)
          echo "今日拦截: $BANS 次"
          if [ "$BANS" -gt 0 ]; then
            echo "最近10条:"
            tail -10 /var/log/novel-shield-bans.log
          fi
          echo ""
          echo "─── iptables 扫描引流规则 ───"
          iptables -t nat -L PREROUTING --line-numbers 2>/dev/null | grep -E "REDIRECT|target" | head -15 || echo "无规则或无权限查看"
          echo ""
          echo "─── 蜜罐响应测试 ───"
          HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 http://127.0.0.1/ 2>/dev/null || echo "超时")
          echo "蜜罐 HTTP 响应码: $HTTP_CODE"
          echo ""
          echo "─── SSL 证书状态 ───"
          if [ -f /etc/letsencrypt/live/novel.guanghuyaoming.com/fullchain.pem ]; then
            EXPIRY=$(openssl x509 -enddate -noout -in /etc/letsencrypt/live/novel.guanghuyaoming.com/fullchain.pem 2>/dev/null || echo "无法读取")
            echo "SSL 证书到期: $EXPIRY"
          else
            echo "SSL 证书: 未申请 (运行 setup-ssl 动作)"
          fi
          echo ""
          echo "═══ 检查完成 ═══"
          ENDSSH

  # ═══════════════════════════════════════════════════════
  # Job 4: 回滚
  # ═══════════════════════════════════════════════════════
  rollback:
    name: '⏪ 回滚配置'
    runs-on: ubuntu-latest
    permissions: {}
    if: github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'rollback'

    steps:
      - name: '🔑 配置 SSH'
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.ZY_NOVEL_KEY }}" > ~/.ssh/novel_key
          chmod 600 ~/.ssh/novel_key
          ssh-keyscan -H ${{ secrets.ZY_NOVEL_HOST }} >> ~/.ssh/known_hosts

      - name: '⏪ 回滚到上一份配置'
        run: |
          ssh -i ~/.ssh/novel_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          set -e
          LATEST_BAK=$(ls -t /etc/nginx/sites-available/novel-mirror-shield.conf.bak.* 2>/dev/null | head -1)
          if [ -z "$LATEST_BAK" ]; then
            echo "✗ 没有找到备份文件，无法回滚"
            exit 1
          fi
          echo "回滚到: $LATEST_BAK"
          cp "$LATEST_BAK" /etc/nginx/sites-available/novel-mirror-shield.conf
          nginx -t
          systemctl reload nginx
          echo "✓ 回滚成功"
          ENDSSH
