tractatus/docs/PHASE-2-DEPLOYMENT-GUIDE.md
TheFlow 2298d36bed fix(submissions): restructure Economist package and fix article display
- Create Economist SubmissionTracking package correctly:
  * mainArticle = full blog post content
  * coverLetter = 216-word SIR— letter
  * Links to blog post via blogPostId
- Archive 'Letter to The Economist' from blog posts (it's the cover letter)
- Fix date display on article cards (use published_at)
- Target publication already displaying via blue badge

Database changes:
- Make blogPostId optional in SubmissionTracking model
- Economist package ID: 68fa85ae49d4900e7f2ecd83
- Le Monde package ID: 68fa2abd2e6acd5691932150

Next: Enhanced modal with tabs, validation, export

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 08:47:42 +13:00

34 KiB

Phase 2 Deployment Guide - Granular Task Instructions

Project: Tractatus AI Safety Framework Domain: agenticgovernance.digital VPS: vps-7f023e40.vps.ovh.net (OVHCloud) Created: 2025-10-07 Status: ACTIVE DEPLOYMENT


Table of Contents

  1. Week 0: Pre-Deployment Preparation
  2. Week 1: Infrastructure Setup
  3. Week 2: Application Deployment
  4. Week 3: Security Hardening
  5. Week 4: Monitoring & Testing
  6. Week 5-8: AI Features
  7. Week 9-12: Soft Launch
  8. Emergency Procedures

Week 0: Pre-Deployment Preparation

Day 0.1: OVHCloud VPS Assessment

Current VPS: vps-7f023e40.vps.ovh.net

Tasks:

  1. Check VPS specifications in OVHCloud control panel:

    • CPU cores (need 2+)
    • RAM (need 4GB+)
    • Disk space (need 80GB+)
    • Bandwidth allocation
    • Current OS (Ubuntu 22.04 LTS preferred)
  2. Verify VPS location:

    • Confirm datacenter region (Singapore/Australia preferred)
    • Check latency to target users
  3. Check current VPS state:

    • Is it a fresh install or has existing services?
    • Any data to backup before proceeding?
    • Current SSH access method (password or key?)

Commands to Run (if you have SSH access):

# Check OS version
cat /etc/os-release

# Check system resources
free -h                    # RAM
df -h                      # Disk space
nproc                      # CPU cores
ip addr show               # Network interfaces
systemctl list-units       # Running services

Decision Points:

  • Fresh install or clean existing VPS?
  • Keep existing OS or reinstall Ubuntu 22.04 LTS?

Day 0.2: Generate Secrets

Tasks:

  1. Generate JWT Secret:
# On your local machine
openssl rand -base64 48
  • Copy output (64 characters)
  • Store in password manager (1Password, Bitwarden, etc.)
  • Label: "Tractatus JWT_SECRET (Production)"
  1. Generate MongoDB Password:
openssl rand -base64 32
  • Copy output (44 characters)
  • Store in password manager
  • Label: "Tractatus MongoDB tractatus_user password"
  1. Generate MongoDB Root Password:
openssl rand -base64 32
  • Store in password manager
  • Label: "Tractatus MongoDB root password"
  1. Generate SSH Key Pair (for Tractatus deployments):
ssh-keygen -t ed25519 -C "tractatus-deploy@agenticgovernance.digital" -f ~/.ssh/tractatus_deploy
  • Private key: ~/.ssh/tractatus_deploy (keep secure)
  • Public key: ~/.ssh/tractatus_deploy.pub (will add to VPS)

Security Checklist:

  • All secrets stored in password manager (never in Git)
  • SSH private key has passphrase
  • Backup of password manager vault

Day 0.3: DNS Preparation

Tasks:

  1. Access OVHCloud DNS Management:

    • Navigate to: Domains → agenticgovernance.digital → DNS Zone
    • Familiarize with interface
  2. Get VPS IP Address from OVHCloud:

    • VPS Dashboard → vps-7f023e40.vps.ovh.net → IP Addresses
    • Note IPv4 address: ___.___.___.___
    • Note IPv6 address (if available): ____:____:____:____
  3. Prepare DNS Records (don't configure yet, just prepare):

Type  | Name | Value              | TTL
------|------|-------------------|-----
A     | @    | <VPS_IPv4>        | 300 (5 min for testing)
A     | www  | <VPS_IPv4>        | 300
AAAA  | @    | <VPS_IPv6>        | 300 (if available)
AAAA  | www  | <VPS_IPv6>        | 300 (if available)

Note: We'll configure DNS in Week 1 after server is ready.


Day 0.4: Local Repository Preparation

Tasks:

  1. Create production branch:
cd /home/theflow/projects/tractatus
git checkout -b production
git push -u origin production
git checkout main
  1. Create .env.production template:
cat > .env.production << 'EOF'
# Tractatus Production Environment
NODE_ENV=production
PORT=9000

# Application
APP_NAME=Tractatus
APP_DOMAIN=agenticgovernance.digital
APP_URL=https://agenticgovernance.digital

# MongoDB
MONGODB_URI=mongodb://tractatus_user:<PASSWORD>@localhost:27017/tractatus_prod?authSource=tractatus_prod
MONGODB_PORT=27017
MONGODB_DATABASE=tractatus_prod

# JWT
JWT_SECRET=<GENERATE_FROM_DAY_0.2>
JWT_EXPIRY=7d

# Claude API (Week 5+)
CLAUDE_API_KEY=<TO_BE_ADDED>
CLAUDE_MODEL=claude-sonnet-4-5-20250929

# Admin
ADMIN_EMAIL=admin@agenticgovernance.digital

# Security
SESSION_SECRET=<GENERATE_ANOTHER_SECRET>
COOKIE_SECURE=true
COOKIE_SAMESITE=strict
EOF
  1. Add .env.production to .gitignore:
echo ".env.production" >> .gitignore
git add .gitignore
git commit -m "chore: add .env.production to gitignore"
  1. Test production build locally:
NODE_ENV=production npm start
# Verify app starts without errors
# Ctrl+C to stop

Week 1: Infrastructure Setup

Day 1.1: Initial VPS Access & User Setup

Tasks:

  1. Access VPS via SSH (OVHCloud provides root access):
ssh root@vps-7f023e40.vps.ovh.net
# Or use IP: ssh root@<VPS_IP>
  1. Update system packages:
apt update && apt upgrade -y
  1. Create non-root user:
adduser tractatus
# Set password (use password manager to generate & store)
# Full name: Tractatus Application
# Leave other fields blank (press Enter)

# Add to sudo group
usermod -aG sudo tractatus
  1. Set up SSH key authentication for tractatus user:
# Still as root
mkdir -p /home/tractatus/.ssh
chmod 700 /home/tractatus/.ssh

# Copy your SSH public key (from Day 0.2)
# On your LOCAL machine, copy the public key:
cat ~/.ssh/tractatus_deploy.pub

# Back on VPS, paste it:
nano /home/tractatus/.ssh/authorized_keys
# Paste the public key, save (Ctrl+O, Enter, Ctrl+X)

chmod 600 /home/tractatus/.ssh/authorized_keys
chown -R tractatus:tractatus /home/tractatus/.ssh
  1. Test SSH access as tractatus user:
# From your LOCAL machine (new terminal):
ssh -i ~/.ssh/tractatus_deploy tractatus@vps-7f023e04.vps.ovh.net

# If successful, you should see tractatus@vps-7f023e40:~$
  1. Configure sudo without password (for deployment automation):
# On VPS, as root:
visudo

# Add this line at the end:
tractatus ALL=(ALL) NOPASSWD:ALL

# Save and exit (Ctrl+O, Enter, Ctrl+X if nano, or :wq if vim)

Day 1.2: Firewall & SSH Hardening

Tasks:

  1. Install UFW (Uncomplicated Firewall):
# As tractatus user on VPS:
sudo apt install ufw -y
  1. Configure UFW rules (CRITICAL - don't lock yourself out):
# Allow SSH from your current IP (safer)
# Get your IP: curl ifconfig.me
sudo ufw allow from <YOUR_IP> to any port 22

# Or allow SSH from anywhere (less secure but more flexible):
sudo ufw allow 22/tcp

# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Check rules before enabling
sudo ufw show added
  1. Enable UFW:
sudo ufw enable
# Type 'y' to confirm

# Verify status
sudo ufw status verbose
  1. Harden SSH configuration:
sudo nano /etc/ssh/sshd_config

# Find and modify these lines:
PermitRootLogin no                    # Disable root login
PasswordAuthentication no             # Disable password auth
PubkeyAuthentication yes              # Enable key-based auth
Port 22                               # Keep default (or change to custom)
MaxAuthTries 3                        # Limit authentication attempts
ClientAliveInterval 300               # Timeout idle sessions (5 min)
ClientAliveCountMax 2                 # Max missed keepalives

# Save and exit
  1. Restart SSH service:
sudo systemctl restart sshd

# Verify SSH is still working (open NEW terminal, don't close current one):
ssh -i ~/.ssh/tractatus_deploy tractatus@vps-7f023e40.vps.ovh.net
  1. Install Fail2ban:
sudo apt install fail2ban -y

# Create local configuration
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

# Edit configuration
sudo nano /etc/fail2ban/jail.local

# Find [sshd] section and modify:
[sshd]
enabled = true
port = 22
maxretry = 3
bantime = 3600
findtime = 600

# Save and exit
  1. Start Fail2ban:
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo fail2ban-client status sshd

Day 1.3: Install Node.js & Dependencies

Tasks:

  1. Install Node.js 18 LTS (via NodeSource):
# Download and run NodeSource setup script
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -

# Install Node.js
sudo apt install nodejs -y

# Verify installation
node --version    # Should show v18.x.x
npm --version     # Should show 9.x.x or 10.x.x
  1. Install build tools (needed for some npm packages):
sudo apt install build-essential -y
  1. Install Git:
sudo apt install git -y
git --version
  1. Install PM2 (process manager for Node.js):
sudo npm install -g pm2
pm2 --version
  1. Configure PM2 to start on boot:
pm2 startup systemd -u tractatus --hp /home/tractatus
# Copy and run the command PM2 outputs (starts with 'sudo env PATH=...')

Day 1.4: Install & Configure MongoDB

Tasks:

  1. Import MongoDB GPG key:
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
   sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor
  1. Add MongoDB repository:
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | \
   sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
  1. Install MongoDB:
sudo apt update
sudo apt install mongodb-org -y
  1. Start MongoDB:
sudo systemctl start mongod
sudo systemctl enable mongod
sudo systemctl status mongod
  1. Create MongoDB admin user:
mongosh

# In MongoDB shell:
use admin
db.createUser({
  user: "admin",
  pwd: "<MONGODB_ROOT_PASSWORD_FROM_DAY_0.2>",
  roles: ["root"]
})

# Exit MongoDB shell
exit
  1. Enable MongoDB authentication:
sudo nano /etc/mongod.conf

# Find the security section and modify:
security:
  authorization: enabled

# Save and exit
  1. Restart MongoDB:
sudo systemctl restart mongod
  1. Create Tractatus database and user:
mongosh -u admin -p --authenticationDatabase admin

# In MongoDB shell (enter admin password when prompted):
use tractatus_prod

db.createUser({
  user: "tractatus_user",
  pwd: "<MONGODB_PASSWORD_FROM_DAY_0.2>",
  roles: [
    { role: "readWrite", db: "tractatus_prod" },
    { role: "dbAdmin", db: "tractatus_prod" }
  ]
})

# Test authentication
exit

mongosh -u tractatus_user -p --authenticationDatabase tractatus_prod tractatus_prod
# Enter tractatus_user password when prompted
# If successful, you'll see tractatus_prod> prompt

exit

Day 1.5: Install & Configure Nginx

Tasks:

  1. Install Nginx:
sudo apt install nginx -y

# Verify installation
nginx -v
sudo systemctl status nginx
  1. Configure Nginx for Tractatus (HTTP only, SSL in Day 1.6):
sudo nano /etc/nginx/sites-available/tractatus

# Paste this configuration:
# Tractatus Production - HTTP Only (SSL will be added)
server {
    listen 80;
    listen [::]:80;
    server_name agenticgovernance.digital www.agenticgovernance.digital;

    # Temporary: Redirect to show "Coming Soon"
    location / {
        return 200 'Tractatus Framework - Deploying...';
        add_header Content-Type text/plain;
    }
}
  1. Enable the site:
sudo ln -s /etc/nginx/sites-available/tractatus /etc/nginx/sites-enabled/

# Remove default site
sudo rm /etc/nginx/sites-enabled/default

# Test configuration
sudo nginx -t

# Reload Nginx
sudo systemctl reload nginx
  1. Test Nginx (from your local machine):
# If DNS is configured:
curl http://agenticgovernance.digital

# Or use VPS IP:
curl http://<VPS_IP>

# Should see: "Tractatus Framework - Deploying..."

Day 1.6: Configure DNS

Tasks:

  1. Get VPS IP address:
# On VPS:
ip addr show | grep 'inet '
# Note the public IPv4 (not 127.0.0.1)
  1. Configure DNS in OVHCloud:

    • Navigate to: Domains → agenticgovernance.digital → DNS Zone
    • Click "Add an entry"

    Add A record:

    • Type: A
    • Subdomain: (leave empty for @)
    • Target: <VPS_IPv4>
    • TTL: 300 (5 minutes for testing)

    Add A record for www:

    • Type: A
    • Subdomain: www
    • Target: <VPS_IPv4>
    • TTL: 300
  2. Wait for DNS propagation (5-30 minutes):

# From your LOCAL machine:
dig agenticgovernance.digital +short
# Should return VPS IP

dig www.agenticgovernance.digital +short
# Should return VPS IP

# Or use:
nslookup agenticgovernance.digital
  1. Test DNS with browser:

Day 1.7: Install SSL/TLS with Let's Encrypt

Tasks:

  1. Install Certbot:
sudo apt install certbot python3-certbot-nginx -y
  1. Obtain SSL certificate:
sudo certbot --nginx -d agenticgovernance.digital -d www.agenticgovernance.digital

# Follow prompts:
# - Email: admin@agenticgovernance.digital
# - Agree to Terms of Service: Yes (Y)
# - Share email with EFF: Your choice (Y/N)
# - Redirect HTTP to HTTPS: Yes (2)
  1. Test SSL certificate:

  2. Test auto-renewal:

sudo certbot renew --dry-run
# Should complete without errors
  1. Verify Nginx configuration:
sudo cat /etc/nginx/sites-available/tractatus
# Should now include SSL configuration added by Certbot

Week 2: Application Deployment

Day 2.1: Clone Repository & Setup

Tasks:

  1. Create application directory:
# On VPS as tractatus user:
sudo mkdir -p /var/www/tractatus
sudo chown tractatus:tractatus /var/www/tractatus
cd /var/www/tractatus
  1. Clone repository:
# Option A: HTTPS (simpler, but need GitHub token for private repos)
git clone https://github.com/<YOUR_USERNAME>/tractatus.git .

# Option B: SSH (requires SSH key setup on GitHub)
# First, generate SSH key on VPS:
ssh-keygen -t ed25519 -C "vps@agenticgovernance.digital" -f ~/.ssh/github_tractatus
cat ~/.ssh/github_tractatus.pub
# Add public key to GitHub: Settings → SSH Keys → New SSH Key

git clone git@github.com:<YOUR_USERNAME>/tractatus.git .
  1. Checkout production branch:
git checkout production
git pull origin production
  1. Install dependencies:
npm ci --production
# Use 'ci' instead of 'install' for reproducible builds

Day 2.2: Configure Environment

Tasks:

  1. Create production .env file:
nano /var/www/tractatus/.env

# Paste (with secrets from Day 0.2):
NODE_ENV=production
PORT=9000

APP_NAME=Tractatus
APP_DOMAIN=agenticgovernance.digital
APP_URL=https://agenticgovernance.digital

MONGODB_URI=mongodb://tractatus_user:<MONGODB_PASSWORD>@localhost:27017/tractatus_prod?authSource=tractatus_prod
MONGODB_PORT=27017
MONGODB_DATABASE=tractatus_prod

JWT_SECRET=<JWT_SECRET>
JWT_EXPIRY=7d

ADMIN_EMAIL=admin@agenticgovernance.digital

SESSION_SECRET=<ANOTHER_SECRET>
COOKIE_SECURE=true
COOKIE_SAMESITE=strict

# Save and exit
  1. Secure .env file:
chmod 600 /var/www/tractatus/.env
chown tractatus:tractatus /var/www/tractatus/.env
  1. Initialize MongoDB (seed collections):
cd /var/www/tractatus
node scripts/init-db.js
  1. Create admin user:
node scripts/seed-admin.js
# Note the admin credentials output

Day 2.3: Configure Nginx Reverse Proxy

Tasks:

  1. Update Nginx configuration:
sudo nano /etc/nginx/sites-available/tractatus

Replace with:

# Tractatus Production - Full Configuration
upstream tractatus_backend {
    server 127.0.0.1:9000;
    keepalive 64;
}

# Redirect www to non-www
server {
    listen 80;
    listen [::]:80;
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name www.agenticgovernance.digital;

    ssl_certificate /etc/letsencrypt/live/agenticgovernance.digital/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/agenticgovernance.digital/privkey.pem;

    return 301 https://agenticgovernance.digital$request_uri;
}

# Main server block
server {
    listen 80;
    listen [::]:80;
    server_name agenticgovernance.digital;

    # Redirect HTTP to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name agenticgovernance.digital;

    # SSL Configuration
    ssl_certificate /etc/letsencrypt/live/agenticgovernance.digital/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/agenticgovernance.digital/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # Security Headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

    # Content Security Policy
    add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none';" always;

    # Root and index
    root /var/www/tractatus/public;
    index index.html;

    # Logging
    access_log /var/log/nginx/tractatus-access.log;
    error_log /var/log/nginx/tractatus-error.log;

    # Static files
    location /css {
        alias /var/www/tractatus/public/css;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    location /js {
        alias /var/www/tractatus/public/js;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    location /images {
        alias /var/www/tractatus/public/images;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Proxy to Node.js application
    location / {
        try_files $uri $uri/ @proxy;
    }

    location @proxy {
        proxy_pass http://tractatus_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
        proxy_read_timeout 90;
    }

    # Health check endpoint
    location /health {
        proxy_pass http://tractatus_backend/health;
        access_log off;
    }
}
  1. Test Nginx configuration:
sudo nginx -t
  1. Reload Nginx:
sudo systemctl reload nginx

Day 2.4: Start Application with PM2

Tasks:

  1. Create PM2 ecosystem file:
nano /var/www/tractatus/ecosystem.config.js
module.exports = {
  apps: [{
    name: 'tractatus',
    script: './src/server.js',
    instances: 2,
    exec_mode: 'cluster',
    env: {
      NODE_ENV: 'production'
    },
    error_file: '/var/www/tractatus/logs/pm2-error.log',
    out_file: '/var/www/tractatus/logs/pm2-out.log',
    log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
    max_memory_restart: '500M',
    autorestart: true,
    watch: false
  }]
};
  1. Create logs directory:
mkdir -p /var/www/tractatus/logs
  1. Start application:
cd /var/www/tractatus
pm2 start ecosystem.config.js

# Check status
pm2 status

# View logs
pm2 logs tractatus --lines 50
  1. Save PM2 configuration:
pm2 save
  1. Test application:
# Local test
curl http://localhost:9000/health

# Public test
curl https://agenticgovernance.digital/health
  1. Open browser and test:
    • Visit: https://agenticgovernance.digital
    • Should see Tractatus homepage
    • Test navigation (Researcher, Implementer, Advocate paths)
    • Test demos (27027 incident, classification, boundary)

Week 3: Security Hardening

Day 3.1: Automated Security Updates

Tasks:

  1. Install unattended-upgrades:
sudo apt install unattended-upgrades -y
  1. Configure automatic updates:
sudo dpkg-reconfigure -plow unattended-upgrades
# Select "Yes" to enable
  1. Verify configuration:
sudo cat /etc/apt/apt.conf.d/20auto-upgrades

# Should show:
# APT::Periodic::Update-Package-Lists "1";
# APT::Periodic::Unattended-Upgrade "1";

Day 3.2: Implement Rate Limiting

Tasks:

  1. Configure Nginx rate limiting:
sudo nano /etc/nginx/nginx.conf

# In http block, add:
http {
    # ... existing config ...

    # Rate limiting zones
    limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=api:10m rate=5r/s;
    limit_req_zone $binary_remote_addr zone=auth:10m rate=3r/m;

    # ... rest of config ...
}
  1. Apply rate limits in site config:
sudo nano /etc/nginx/sites-available/tractatus

# Add to server block:
    # Rate limiting
    location /auth {
        limit_req zone=auth burst=5;
        proxy_pass http://tractatus_backend;
        # ... other proxy settings ...
    }

    location /api {
        limit_req zone=api burst=10 nodelay;
        proxy_pass http://tractatus_backend;
        # ... other proxy settings ...
    }

    location / {
        limit_req zone=general burst=20 nodelay;
        # ... existing config ...
    }
  1. Test and reload:
sudo nginx -t
sudo systemctl reload nginx

Day 3.3: Setup Automated Backups

Tasks:

  1. Create backup script:
sudo nano /usr/local/bin/tractatus-backup.sh
#!/bin/bash
# Tractatus MongoDB Backup Script

BACKUP_DIR="/var/backups/tractatus"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="tractatus_backup_${DATE}.gz"
RETENTION_DAYS=7

# Create backup directory
mkdir -p $BACKUP_DIR

# Dump MongoDB database
mongodump --uri="mongodb://tractatus_user:<PASSWORD>@localhost:27017/tractatus_prod?authSource=tractatus_prod" \
  --gzip --archive="${BACKUP_DIR}/${BACKUP_FILE}"

# Remove old backups
find $BACKUP_DIR -name "tractatus_backup_*.gz" -mtime +${RETENTION_DAYS} -delete

# Log result
echo "[$(date)] Backup completed: ${BACKUP_FILE}" >> /var/log/tractatus-backup.log
  1. Make script executable:
sudo chmod +x /usr/local/bin/tractatus-backup.sh
  1. Test backup script:
sudo /usr/local/bin/tractatus-backup.sh
ls -lh /var/backups/tractatus/
  1. Schedule daily backups with cron:
sudo crontab -e

# Add this line (runs daily at 2 AM):
0 2 * * * /usr/local/bin/tractatus-backup.sh

Day 3.4: Configure Fail2ban for Nginx

Tasks:

  1. Create Nginx jail:
sudo nano /etc/fail2ban/jail.local

# Add:
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/tractatus-error.log

[nginx-limit-req]
enabled = true
port = http,https
logpath = /var/log/nginx/tractatus-error.log
findtime = 600
maxretry = 10
  1. Restart Fail2ban:
sudo systemctl restart fail2ban
sudo fail2ban-client status

Week 4: Monitoring & Testing

Day 4.1: Setup Error Monitoring (Sentry)

Tasks:

  1. Create Sentry account at sentry.io (free tier)

  2. Create new project:

    • Platform: Node.js
    • Project name: tractatus-production
  3. Get DSN (Data Source Name) from Sentry dashboard

  4. Install Sentry SDK:

cd /var/www/tractatus
npm install @sentry/node --save
  1. Add Sentry DSN to .env:
nano /var/www/tractatus/.env

# Add:
SENTRY_DSN=<YOUR_SENTRY_DSN>
  1. Initialize Sentry in application:
nano /var/www/tractatus/src/server.js

# Add at the top (after require statements):
const Sentry = require('@sentry/node');

if (process.env.SENTRY_DSN) {
  Sentry.init({
    dsn: process.env.SENTRY_DSN,
    environment: process.env.NODE_ENV,
    tracesSampleRate: 0.1, // 10% of transactions
  });
}

# Add Sentry error handler middleware (before other error handlers):
app.use(Sentry.Handlers.errorHandler());
  1. Restart application:
pm2 restart tractatus
  1. Test error tracking:
    • Visit Sentry dashboard
    • Trigger a test error on the site
    • Verify error appears in Sentry

Day 4.2: Setup Uptime Monitoring

Tasks:

  1. Create UptimeRobot account at uptimerobot.com (free tier)

  2. Add monitor:

  3. Configure alerts:

  4. Test monitor:

    • Stop PM2: pm2 stop tractatus
    • Wait for alert (5 minutes)
    • Restart: pm2 start tractatus
    • Verify "UP" notification

Day 4.3: Performance Testing

Tasks:

  1. Test Core Web Vitals:

  2. Run Lighthouse audit (Chrome DevTools):

    • Open Chrome DevTools (F12)
    • Lighthouse tab
    • Run audit (Desktop)
    • Check: Performance, Accessibility, Best Practices, SEO
    • Target: All >90
  3. Load testing with Apache Bench:

# On local machine:
ab -n 1000 -c 10 https://agenticgovernance.digital/

# Should handle 1000 requests with 10 concurrent without errors
  1. Check response times:
curl -w "@-" -o /dev/null -s https://agenticgovernance.digital/ <<'EOF'
    time_namelookup:  %{time_namelookup}s\n
       time_connect:  %{time_connect}s\n
    time_appconnect:  %{time_appconnect}s\n
   time_pretransfer:  %{time_pretransfer}s\n
      time_redirect:  %{time_redirect}s\n
 time_starttransfer:  %{time_starttransfer}s\n
                    ----------\n
         time_total:  %{time_total}s\n
EOF

# Target: time_total < 2.5s

Day 4.4: Security Audit

Tasks:

  1. Run SSL Labs test:

  2. Check security headers:

  3. Scan for vulnerabilities:

# On VPS:
sudo apt install lynis -y
sudo lynis audit system

# Review warnings in: /var/log/lynis-report.dat
  1. Check npm dependencies:
cd /var/www/tractatus
npm audit

# Fix any high/critical vulnerabilities:
npm audit fix

Week 5-8: AI Features

Week 5: Claude API Integration

Tasks:

  1. Create Anthropic account and obtain production API key

  2. Add Claude API key to .env:

nano /var/www/tractatus/.env

# Add:
CLAUDE_API_KEY=<YOUR_ANTHROPIC_API_KEY>
CLAUDE_MODEL=claude-sonnet-4-5-20250929
CLAUDE_MAX_TOKENS=4096
  1. Install Claude SDK:
cd /var/www/tractatus
npm install @anthropic-ai/sdk --save
  1. Deploy updated code:
git pull origin production
npm install
pm2 restart tractatus
  1. Test Claude integration:
    • Test blog topic suggestion endpoint
    • Monitor API usage in Anthropic dashboard
    • Verify rate limiting is working

Week 6-7: Implement AI Features

Reference: See PHASE-2-ROADMAP.md for detailed AI feature specifications

Tasks:

  1. Blog Curation System:

    • Implement topic suggestion API
    • Implement outline generation API
    • Create human approval workflow
    • Test end-to-end
  2. Media Inquiry Triage:

    • Implement classification API
    • Implement draft response generator
    • Create moderation queue
    • Test all priority levels
  3. Case Study Portal:

    • Implement submission form
    • Implement relevance analysis API
    • Create moderation workflow
    • Test publication pipeline

Week 9-12: Soft Launch

Week 9: Pre-Launch Testing

Tasks:

  1. End-to-end testing of all features
  2. Governance compliance audit (verify TRA-OPS-* policies)
  3. User acceptance testing (internal)
  4. Performance optimization
  5. Final security review

Week 10: Soft Launch Preparation

Tasks:

  1. Finalize invitation list (20-50 users)
  2. Prepare email templates (use PHASE-2-EMAIL-TEMPLATES.md)
  3. Create feedback survey (Google Form or TypeForm)
  4. Set up analytics (Plausible or privacy-respecting alternative)

Week 11: Send Invitations

Tasks:

  1. Send invitations (personalized, BCC all recipients)
  2. Monitor responses and platform usage
  3. Respond to inquiries within SLAs
  4. Collect feedback via survey

Week 12: Iteration & Analysis

Tasks:

  1. Analyze feedback (quantitative + qualitative)
  2. Implement improvements based on user input
  3. Prepare summary report for Phase 2 completion
  4. Decision: Proceed to Phase 3 (Public Launch) or extend soft launch

Emergency Procedures

Application Down

# Check PM2 status
pm2 status

# View logs
pm2 logs tractatus --lines 100

# Restart application
pm2 restart tractatus

# If persistent issues, check MongoDB
sudo systemctl status mongod

# Check Nginx
sudo systemctl status nginx
sudo nginx -t

Database Issues

# Check MongoDB status
sudo systemctl status mongod

# View MongoDB logs
sudo tail -f /var/log/mongodb/mongod.log

# Restart MongoDB
sudo systemctl restart mongod

# Restore from backup
mongorestore --uri="mongodb://tractatus_user:<PASSWORD>@localhost:27017/tractatus_prod?authSource=tractatus_prod" \
  --gzip --archive=/var/backups/tractatus/tractatus_backup_YYYYMMDD_HHMMSS.gz

Server Compromised

# Immediate actions:
# 1. Take server offline
sudo ufw deny 80/tcp
sudo ufw deny 443/tcp

# 2. Kill application
pm2 stop all

# 3. Review access logs
sudo tail -n 1000 /var/log/nginx/tractatus-access.log
sudo tail -n 1000 /var/log/auth.log

# 4. Check for unauthorized users
sudo cat /etc/passwd

# 5. Review Fail2ban status
sudo fail2ban-client status

# 6. Contact OVHCloud support if needed

SSL Certificate Expiry

# Check certificate expiry
sudo certbot certificates

# Renew manually
sudo certbot renew

# Test auto-renewal
sudo certbot renew --dry-run

# Reload Nginx
sudo systemctl reload nginx

Rollback Procedures

Rollback Application

# Stop current version
pm2 stop tractatus

# Checkout previous version
cd /var/www/tractatus
git log --oneline -10  # Find commit hash
git checkout <previous_commit_hash>

# Reinstall dependencies
npm ci --production

# Restart
pm2 start ecosystem.config.js
pm2 save

Rollback Database

# List available backups
ls -lh /var/backups/tractatus/

# Restore specific backup
mongorestore --uri="mongodb://tractatus_user:<PASSWORD>@localhost:27017/tractatus_prod?authSource=tractatus_prod" \
  --drop \
  --gzip --archive=/var/backups/tractatus/tractatus_backup_YYYYMMDD_HHMMSS.gz

Maintenance Schedule

Daily

  • Check uptime monitoring (automated)
  • Review error logs (Sentry)
  • Monitor API usage (Anthropic dashboard)

Weekly

  • Review Nginx access logs
  • Check disk space: df -h
  • Review PM2 logs
  • Check for security updates: sudo apt update && sudo apt list --upgradable

Monthly

  • Review all backups (test restore)
  • Analyze analytics data
  • Review TRA-OPS-* compliance
  • Update dependencies: npm outdated

Quarterly

  • Full security audit
  • Performance optimization review
  • Governance document review (TRA-OPS-*)
  • SSL certificate renewal check

Useful Commands Reference

PM2

pm2 status                      # Show all processes
pm2 logs tractatus              # View logs
pm2 restart tractatus           # Restart app
pm2 reload tractatus            # Zero-downtime reload
pm2 stop tractatus              # Stop app
pm2 delete tractatus            # Remove from PM2
pm2 monit                       # Monitor resources
pm2 save                        # Save current config

Nginx

sudo nginx -t                   # Test configuration
sudo systemctl reload nginx     # Reload (no downtime)
sudo systemctl restart nginx    # Restart (brief downtime)
sudo systemctl status nginx     # Check status
sudo tail -f /var/log/nginx/tractatus-error.log  # Watch errors

MongoDB

sudo systemctl status mongod    # Check status
sudo systemctl restart mongod   # Restart
mongosh -u tractatus_user -p --authenticationDatabase tractatus_prod tractatus_prod  # Connect

Git

git status                      # Check working tree
git pull origin production      # Update code
git log --oneline -10           # View recent commits
git checkout <commit>           # Rollback to commit

System

df -h                           # Disk usage
free -h                         # Memory usage
top                             # CPU/process monitor
sudo ufw status                 # Firewall status
sudo fail2ban-client status     # Fail2ban status

Document Status

Created: 2025-10-07 Last Updated: 2025-10-07 Status: ACTIVE - Ready for deployment Next Review: After Week 4 completion


End of Deployment Guide