Deployment
Deployment Guide

Deployment Overview

This guide covers deploying the MyNATCA platform applications on Vercel, including the Discord bot web interface, Member Hub, and other Next.js/Vue.js applications.

Prerequisites

Required Accounts

  • Vercel Account: Pro plan recommended for production
  • GitHub Account: For repository integration
  • Custom Domain: For production deployments

Required Setup

  • Applications pushed to GitHub repositories
  • Environment variables documented
  • Database connections configured
  • Auth0 applications set up

Project Structure for Vercel

Discord Bot Application

mynatca-discord/
├── pages/                  # Next.js pages (API routes)
│   ├── api/
│   │   ├── auth/          # Auth0 callback handlers
│   │   ├── verify/        # Verification endpoints
│   │   └── webhook/       # Discord webhooks
│   ├── verify/            # Verification UI pages
│   └── _app.js           # App configuration
├── vercel.json            # Vercel configuration
├── next.config.js         # Next.js configuration
└── package.json          # Dependencies and scripts

Platform API Application

mynatca-platform/
├── pages/
│   └── api/              # API endpoints
│       ├── sync/         # Data sync endpoints
│       ├── health/       # Health check endpoints
│       └── admin/        # Administrative endpoints
├── vercel.json           # Vercel configuration
└── package.json          # Dependencies and scripts

Vercel Configuration

Discord Bot Configuration

Create vercel.json in the Discord bot repository:

{
  "version": 2,
  "name": "mynatca-discord",
  "alias": ["discord.mynatca.org"],
  "builds": [
    {
      "src": "package.json",
      "use": "@vercel/node"
    }
  ],
  "routes": [
    {
      "src": "/api/(.*)",
      "dest": "/api/$1"
    },
    {
      "src": "/verify/(.*)",
      "dest": "/verify/$1"
    },
    {
      "src": "/(.*)",
      "dest": "/index.html"
    }
  ],
  "env": {
    "NODE_ENV": "production"
  },
  "functions": {
    "pages/api/**/*.js": {
      "maxDuration": 30
    }
  },
  "headers": [
    {
      "source": "/api/(.*)",
      "headers": [
        {
          "key": "Access-Control-Allow-Origin",
          "value": "https://discord.mynatca.org"
        },
        {
          "key": "Access-Control-Allow-Methods",
          "value": "GET, POST, PUT, DELETE, OPTIONS"
        },
        {
          "key": "Access-Control-Allow-Headers",
          "value": "X-Requested-With, Content-Type, Authorization"
        }
      ]
    }
  ],
  "redirects": [
    {
      "source": "/",
      "destination": "/verify",
      "permanent": false
    }
  ]
}

Platform API Configuration

Create vercel.json in the platform repository:

{
  "version": 2,
  "name": "mynatca-platform-api",
  "alias": ["api.mynatca.org"],
  "builds": [
    {
      "src": "package.json",
      "use": "@vercel/node"
    }
  ],
  "routes": [
    {
      "src": "/api/(.*)",
      "dest": "/api/$1"
    }
  ],
  "env": {
    "NODE_ENV": "production"
  },
  "functions": {
    "pages/api/**/*.js": {
      "maxDuration": 60
    },
    "pages/api/sync/**/*.js": {
      "maxDuration": 300
    }
  },
  "crons": [
    {
      "path": "/api/sync/scheduled",
      "schedule": "0 */6 * * *"
    },
    {
      "path": "/api/health/check",
      "schedule": "*/15 * * * *"
    }
  ]
}

Environment Variables Setup

Discord Bot Environment Variables

# Core Discord Configuration
DISCORD_TOKEN=your_discord_bot_token
DISCORD_CLIENT_ID=your_discord_application_id
DISCORD_GUILD_ID=your_discord_server_id
 
# Auth0 Configuration
AUTH0_DOMAIN=natca-prod.us.auth0.com
AUTH0_CLIENT_ID=your_auth0_client_id
AUTH0_CLIENT_SECRET=your_auth0_client_secret
# ⚠️ CRITICAL: AUTH0_SECRET is REQUIRED for NextJS Auth0 SDK
# Generate with: openssl rand -hex 32
AUTH0_SECRET=your_auth0_secret_32_chars_minimum
AUTH0_BASE_URL=https://discord.mynatca.org
AUTH0_ISSUER_BASE_URL=https://natca-prod.us.auth0.com
AUTH0_SCOPE=openid profile email
 
# Database Configuration
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your_supabase_service_key
 
# ⚠️ CRITICAL: Supabase Schema Exposure Required
# In Supabase Dashboard > Settings > API > Exposed schemas
# Add both 'discord' and 'discord_dev' schemas to exposed schemas list
# This allows Discord bot to access verification tables directly
 
# MySQL Configuration (for sync operations)
MYSQL_HOST=your_mysql_host
MYSQL_USER=your_mysql_username
MYSQL_PASS=your_mysql_password
MYSQL_DB=your_mysql_database
 
# Application Configuration
NODE_ENV=production
VERCEL_URL=discord.mynatca.org
WEBHOOK_SECRET=your_webhook_secret
 
# Monitoring
SENTRY_DSN=your_sentry_dsn
LOG_LEVEL=info

Platform API Environment Variables

# Database Configuration
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your_supabase_service_key
 
# MySQL Configuration
MYSQL_HOST=your_mysql_host
MYSQL_USER=your_mysql_username
MYSQL_PASS=your_mysql_password
MYSQL_DB=your_mysql_database
 
# Auth0 Management API
AUTH0_DOMAIN=natca-prod.us.auth0.com
AUTH0_M2M_CLIENT_ID=your_m2m_client_id
AUTH0_M2M_CLIENT_SECRET=your_m2m_client_secret
 
# Session Management (CRITICAL)
SESSION_SECRET=your_long_random_secret_min_32_chars
REDIS_URL=redis://redis:6379
# Note: Generate with: openssl rand -base64 32
 
# Application Configuration
NODE_ENV=production
API_SECRET=your_api_secret
WEBHOOK_SECRET=your_webhook_secret
# CRITICAL: Trust proxy setting (required for reverse proxy deployments)
TRUST_PROXY=1
 
# Rackspace Email Integration
RACKSPACE_API_KEY=your_rackspace_api_key
RACKSPACE_SECRET_KEY=your_rackspace_secret_key
RACKSPACE_CUSTOMER_ID=123456
 
# Intercom Integration
INTERCOM_ACCESS_TOKEN=your_intercom_access_token
 
# Sync Configuration
SYNC_BATCH_SIZE=1000
SYNC_RETRY_COUNT=3
SYNC_TIMEOUT=300000
 
# Monitoring
SENTRY_DSN=your_sentry_dsn
LOG_LEVEL=info

Deployment Process

Initial Setup

1. Install Vercel CLI

npm install -g vercel

2. Login to Vercel

vercel login

3. Link Projects

# In Discord bot repository
cd mynatca-discord
vercel link
 
# In platform repository
cd mynatca-platform
vercel link

Deploy Discord Bot

1. Configure Project Settings

# Set project settings
vercel --prod --confirm
 
# Configure environment variables
vercel env add NODE_ENV production
vercel env add AUTH0_DOMAIN natca-prod.us.auth0.com
vercel env add AUTH0_CLIENT_ID
vercel env add AUTH0_CLIENT_SECRET
# ⚠️ CRITICAL: AUTH0_SECRET must be added or deployment will fail
# Generate with: openssl rand -hex 32
vercel env add AUTH0_SECRET
vercel env add AUTH0_BASE_URL https://discord.mynatca.org
vercel env add AUTH0_ISSUER_BASE_URL https://natca-prod.us.auth0.com
vercel env add DISCORD_TOKEN
vercel env add DISCORD_CLIENT_ID
vercel env add DISCORD_GUILD_ID
vercel env add SUPABASE_URL
vercel env add SUPABASE_KEY
vercel env add MYSQL_HOST
vercel env add MYSQL_USER
vercel env add MYSQL_PASS
vercel env add MYSQL_DB

2. Deploy Application

# Pre-deployment verification
vercel env ls | grep AUTH0_SECRET  # Ensure AUTH0_SECRET is set
 
# Production deployment
vercel --prod
 
# Verify deployment
curl https://discord.mynatca.org/api/health
 
# Test authentication endpoint
curl -I https://discord.mynatca.org/api/auth/login

Deploy Platform API

1. Configure Environment Variables

# In platform repository
vercel env add NODE_ENV production
vercel env add SUPABASE_URL
vercel env add SUPABASE_KEY
vercel env add MYSQL_HOST
vercel env add MYSQL_USER
vercel env add MYSQL_PASS
vercel env add MYSQL_DB
vercel env add AUTH0_DOMAIN
vercel env add AUTH0_M2M_CLIENT_ID
vercel env add AUTH0_M2M_CLIENT_SECRET
vercel env add API_SECRET
vercel env add SYNC_BATCH_SIZE 1000
vercel env add SYNC_RETRY_COUNT 3

2. Deploy Application

# Production deployment
vercel --prod
 
# Verify deployment
curl https://api.mynatca.org/api/health

Custom Domain Configuration

DNS Configuration

# DNS Records (Configure in your DNS provider)
Type: CNAME
Name: discord
Value: cname.vercel-dns.com
 
Type: CNAME
Name: api
Value: cname.vercel-dns.com
 
Type: CNAME
Name: hub
Value: cname.vercel-dns.com

SSL Certificate

Vercel automatically provisions SSL certificates for custom domains:

  • Let's Encrypt certificates
  • Automatic renewal
  • Wildcard support for subdomains

Domain Verification

# Add domain to Vercel project
vercel domains add discord.mynatca.org
vercel domains add api.mynatca.org
vercel domains add hub.mynatca.org
 
# Verify domain ownership
vercel domains verify discord.mynatca.org

Integration with External Services

Auth0 Callback URLs

Update Auth0 applications with production URLs:

Discord Bot Application:
- Allowed Callback URLs: https://discord.mynatca.org/api/auth/callback
- Allowed Logout URLs: https://discord.mynatca.org/api/auth/logout
- Allowed Web Origins: https://discord.mynatca.org

Member Hub Application:
- Allowed Callback URLs: https://hub.mynatca.org/callback
- Allowed Logout URLs: https://hub.mynatca.org
- Allowed Web Origins: https://hub.mynatca.org

Discord Application Configuration

Update Discord application settings:

OAuth2 Redirect URLs:
- https://discord.mynatca.org/api/auth/callback

Interactions Endpoint URL:
- https://discord.mynatca.org/api/interactions

Deployment Automation

GitHub Actions Workflow

# .github/workflows/deploy.yml
name: Deploy to Vercel
 
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
 
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'
 
      - name: Install dependencies
        run: npm ci
 
      - name: Run tests
        run: npm test
 
      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.ORG_ID }}
          vercel-project-id: ${{ secrets.PROJECT_ID }}
          vercel-args: '--prod'
        if: github.ref == 'refs/heads/main'

Environment Promotion Script

#!/bin/bash
# scripts/promote-to-production.sh
 
echo "🚀 Promoting to production..."
 
# Run pre-deployment checks
npm run test
npm run lint
npm run security-audit
 
# Deploy to Vercel
vercel --prod --confirm
 
# Update Auth0 settings
node scripts/update-auth0-production.js
 
# Verify deployment
npm run verify-production
 
echo "✅ Production deployment complete!"

Pre-Deployment Checklist

🔍 Environment Variables Verification

Before deploying to production, verify all required environment variables are set:

# Critical Auth0 variables
vercel env ls | grep AUTH0_SECRET      # Must be present
vercel env ls | grep AUTH0_CLIENT_ID   # Must be present
vercel env ls | grep AUTH0_CLIENT_SECRET # Must be present
vercel env ls | grep AUTH0_DOMAIN      # Must be present
vercel env ls | grep AUTH0_BASE_URL    # Must match deployment URL
 
# Database variables
vercel env ls | grep SUPABASE_URL      # Must be present
vercel env ls | grep SUPABASE_KEY      # Must be present
 
# Discord variables (for Discord bot)
vercel env ls | grep DISCORD_TOKEN     # Must be present
vercel env ls | grep DISCORD_CLIENT_ID # Must be present
vercel env ls | grep DISCORD_GUILD_ID  # Must be present

✅ Required Environment Variables Checklist

Discord Bot Application

  • AUTH0_SECRET - CRITICAL: Generate with openssl rand -hex 32
  • AUTH0_DOMAIN - Set to natca-prod.us.auth0.com
  • AUTH0_CLIENT_ID - From Auth0 dashboard
  • AUTH0_CLIENT_SECRET - From Auth0 dashboard
  • AUTH0_BASE_URL - Set to deployment URL
  • AUTH0_ISSUER_BASE_URL - Set to https://natca-prod.us.auth0.com
  • DISCORD_TOKEN - Bot token from Discord Developer Portal
  • DISCORD_CLIENT_ID - Application ID from Discord Developer Portal
  • DISCORD_GUILD_ID - Server ID where bot will operate
  • SUPABASE_URL - Supabase project URL
  • SUPABASE_KEY - Supabase service role key
  • NODE_ENV - Set to production

Platform API Application

  • SUPABASE_URL - Supabase project URL
  • SUPABASE_KEY - Supabase service role key
  • MYSQL_HOST - MySQL host address
  • MYSQL_USER - MySQL username
  • MYSQL_PASS - MySQL password
  • MYSQL_DB - MySQL database name
  • NODE_ENV - Set to production
  • RACKSPACE_API_KEY - Rackspace Email API key
  • RACKSPACE_SECRET_KEY - Rackspace Email secret key
  • RACKSPACE_CUSTOMER_ID - Rackspace customer account number
  • INTERCOM_ACCESS_TOKEN - Intercom API access token

🔧 Configuration Verification

Auth0 Application Settings

  • Callback URLs include production URL: https://discord.mynatca.org/api/auth/callback
  • Logout URLs include production URL: https://discord.mynatca.org/api/auth/logout
  • Web Origins include production URL: https://discord.mynatca.org
  • Grant Types include Authorization Code and Refresh Token

Discord Application Settings

  • OAuth2 Redirect URLs include: https://discord.mynatca.org/api/auth/callback
  • Interactions Endpoint URL set to: https://discord.mynatca.org/api/interactions
  • Bot Token is valid and has required permissions
  • Application ID matches DISCORD_CLIENT_ID

Database Configuration

  • Supabase project is accessible from production
  • Exposed schemas include discord and discord_dev in Supabase Dashboard > Settings > API
  • MySQL connection works from deployment environment
  • Row Level Security policies are configured correctly
  • Database schema matches latest migrations
  • Schema organization properly separated (dev, discord_dev, public, discord)
  • Production schema migrations applied for positions table (enddate column, unique constraint)
  • Data sync completed from MySQL to Supabase production schema

🚀 Deployment Process Verification

Pre-Deployment Tests

# 1. Verify environment variables
vercel env ls | grep -E "(AUTH0_SECRET|DISCORD_TOKEN|SUPABASE)"
 
# 2. Test configuration locally
vercel dev --listen 3000
curl http://localhost:3000/api/health
 
# 3. Run deployment with verification
vercel --prod --confirm
 
# 4. Wait for deployment to complete
# 5. Verify deployment URL is accessible
curl -I https://discord.mynatca.org/api/health

Post-Deployment Verification

# 1. Health check
curl https://discord.mynatca.org/api/health
# Expected: 200 OK with health status
 
# 2. Auth endpoints
curl -I https://discord.mynatca.org/api/auth/login
# Expected: 302 redirect to Auth0
 
# 3. Database connectivity
curl https://discord.mynatca.org/api/sync/status
# Expected: 200 OK with sync status
 
# 4. Discord bot functionality
# Test /register command in Discord
# Verify verification flow works end-to-end

❌ Common Deployment Failures

"secret" is required Error

Cause: Missing AUTH0_SECRET environment variable Solution: Generate and set AUTH0_SECRET:

openssl rand -hex 32
vercel env add AUTH0_SECRET production

Sessions Not Persisting After Login (CRITICAL)

Cause: Missing trust proxy configuration when deployed behind reverse proxy Symptoms:

  • Users authenticate successfully but immediately logged out
  • Sessions work on localhost but fail on production
  • Secure cookies not being set

Solution: Add trust proxy configuration to server.js:

// Add BEFORE session middleware
app.set('trust proxy', 1);

For Digital Ocean App Platform:

// server.js
const app = express();
 
// Trust Digital Ocean's reverse proxy
app.set('trust proxy', 1);
 
app.use(session({
  cookie: {
    secure: process.env.NODE_ENV === 'production'  // Now works correctly
  }
}));

Verification:

# Test that secure cookie is set
curl -c cookies.txt -v https://platform.natca.org/api/auth/login 2>&1 | grep -i set-cookie
# Should see: Set-Cookie: platform.session=...; Secure; HttpOnly

Database Connection Failures

Cause: Incorrect database credentials or network access Solution: Verify database environment variables and network access

Discord Bot Not Responding

Cause: Incorrect Discord token or permissions Solution: Verify DISCORD_TOKEN and bot permissions in Discord server

Auth0 Callback Errors

Cause: Misconfigured callback URLs in Auth0 dashboard Solution: Update Auth0 application settings with production URLs

Discord Bot Schema Access Errors

Cause: Discord/discord_dev schemas not exposed in Supabase Symptoms:

  • "relation 'discord.verification_requests' does not exist"
  • Discord bot cannot access verification tables
  • 404 errors when querying Discord-specific tables

Solution: Expose required schemas in Supabase:

  1. Navigate to Supabase Dashboard > Settings > API
  2. Scroll to "Exposed schemas" section
  3. Add discord and discord_dev to the list
  4. Save changes and redeploy Discord bot

Verification:

# Test schema access
curl https://your-project.supabase.co/rest/v1/discord.verification_requests \
  -H "apikey: your_anon_key" \
  -H "Authorization: Bearer your_service_key"
# Should return data or empty array, not 404

🔒 Security Verification

Environment Security

  • Different secrets for staging and production environments
  • Secure random generation for AUTH0_SECRET (minimum 32 characters)
  • No hardcoded secrets in source code
  • Production-only access to production databases

Network Security

  • HTTPS enabled for all production URLs
  • Secure headers configured in deployment
  • CORS settings properly configured
  • Rate limiting enabled for API endpoints

📋 Database Migration and Sync Checklist

Before deploying to production, ensure database schema is up-to-date and data is synced:

Migration Rebaseline Process (October 2025)

The MyNATCA platform underwent a migration rebaseline to clean up old migration files and establish a fresh baseline from production.

What Changed:

  • Removed old migration files that were already applied to production
  • Created new baseline migration from production schema: 20251024122438_remote_schema.sql
  • Enables clean supabase db push workflow going forward
  • Prevents accidental schema changes from old migrations

Migration Strategy:

# 1. Pull current production schema as baseline
supabase db pull
 
# This creates: supabase/migrations/20251024122438_remote_schema.sql
# This file represents the CURRENT production database state
 
# 2. For new schema changes, create new migrations after this baseline
supabase migration new add_new_feature
 
# 3. Apply new migrations to production
supabase db push

Important Notes:

  • Old migrations before 20251024122438_remote_schema.sql have been removed
  • The baseline migration contains the complete production schema as of October 24, 2025
  • New migrations should be created after this baseline
  • Never manually edit the baseline migration file

Production Schema Migrations

Positions Table Migrations:

These migrations are now included in the baseline, but documented here for reference:

-- 1. Add enddate column (already in baseline)
ALTER TABLE public.positions
ADD COLUMN IF NOT EXISTS enddate DATE;
 
-- 2. Add unique constraint (already in baseline)
ALTER TABLE public.positions
ADD CONSTRAINT positions_member_position_unique
UNIQUE (membernumber, positiontype);

Running Migrations:

# Option 1: Using Supabase CLI (Recommended)
supabase db push
 
# Option 2: Using psql
psql "postgresql://postgres:[password]@db.[project-ref].supabase.co:5432/postgres" \
  -f migrations/add_positions_enddate.sql
 
# Option 3: Using Supabase SQL Editor
# Navigate to Dashboard > SQL Editor > New Query
# Paste migration SQL and execute

Verification:

# Verify enddate column exists
psql -c "\d public.positions"
 
# Verify unique constraint exists
psql -c "SELECT conname FROM pg_constraint WHERE conrelid = 'public.positions'::regclass;"
 
# Check migration history
supabase migration list

Migration Workflow After Rebaseline:

# 1. Make schema changes locally
# Edit your Supabase schema as needed
 
# 2. Create a new migration
supabase migration new descriptive_name_of_change
 
# 3. Test locally
supabase db reset  # Applies all migrations including new one
npm run dev        # Test your application
 
# 4. Deploy to production
git add supabase/migrations/
git commit -m "Add new schema migration"
git push
 
# 5. Apply migration to production
supabase db push --linked

Data Synchronization

Initial Production Sync:

# Navigate to platform directory
cd platform
 
# Run full production sync
node sync/sync-all.js --env=prod

Expected Output:

🎯 Syncing to public schema
Syncing regions...
✓ Synced 10 regions
Syncing facilities...
✓ Synced 342 facilities
Syncing members...
✓ Synced 15,234 members
Syncing positions...
✓ Synced 1,247 positions
Syncing teams...
✓ Synced 89 teams
All syncs completed successfully!

Individual Table Sync (after initial sync):

# Sync only positions (fast, skips dependencies)
node sync/sync-all.js positions --skip-deps --env=prod
 
# Sync only members
node sync/sync-all.js members --skip-deps --env=prod
 
# Sync only teams
node sync/sync-all.js teams --skip-deps --env=prod

Sync Verification:

# Check record counts
psql -c "SELECT COUNT(*) FROM public.members;"
psql -c "SELECT COUNT(*) FROM public.positions;"
psql -c "SELECT COUNT(*) FROM public.teams;"
 
# Verify recent sync timestamp
psql -c "SELECT MAX(updated_at) FROM public.members;"

📊 Monitoring Setup

Health Monitoring

  • Health endpoints accessible: /api/health
  • Monitoring alerts configured for downtime
  • Performance monitoring enabled
  • Error tracking configured (Sentry, etc.)
  • Data sync monitoring configured to alert on sync failures

Logging Configuration (Updated October 2025)

  • JSON-structured logging enabled on all services
  • OpenSearch configured for log aggregation
  • Log shipping configured (Filebeat, Fluentd, or direct streaming)
  • Index patterns created in OpenSearch Dashboards
  • Error logging captures stack traces with context
  • Access logs for security monitoring
  • Database query logs for performance monitoring

OpenSearch Logging Setup

1. JSON Logging Enabled

Verify all services output JSON logs:

# Discord Bot
docker logs discord-bot | head -1
# Should output: {"timestamp":"...","level":"info","service":"discord-bot",...}
 
# Platform
docker logs platform | head -1
# Should output: {"timestamp":"...","level":"info","service":"platform",...}

2. Log Shipping Configuration

Option A: Filebeat (Recommended)

# filebeat.yml
filebeat.inputs:
  - type: container
    paths:
      - '/var/lib/docker/containers/*/*.log'
    json.keys_under_root: true
    json.add_error_key: true
    processors:
      - add_docker_metadata:
          host: "unix:///var/run/docker.sock"
 
output.elasticsearch:
  hosts: ["opensearch:9200"]
  username: "admin"
  password: "${OPENSEARCH_PASSWORD}"
  indices:
    - index: "discord-bot-logs-%{+yyyy.MM.dd}"
      when.contains:
        container.labels.service: "discord-bot"
    - index: "platform-logs-%{+yyyy.MM.dd}"
      when.contains:
        container.labels.service: "platform"

Option B: Fluentd

# fluent.conf
<source>
  @type tail
  path /var/log/containers/*.log
  pos_file /var/log/fluentd-containers.pos
  tag docker.*
  format json
  time_key timestamp
  time_format %Y-%m-%dT%H:%M:%S.%LZ
</source>
 
<match docker.**>
  @type opensearch
  host opensearch
  port 9200
  user admin
  password ${OPENSEARCH_PASSWORD}
  index_name logs
  logstash_format true
  logstash_prefix logs
</match>

3. OpenSearch Index Patterns

Create index patterns in OpenSearch Dashboards:

// Discord Bot Index Pattern
{
  "index_patterns": ["discord-bot-logs-*"],
  "mappings": {
    "properties": {
      "timestamp": { "type": "date" },
      "level": { "type": "keyword" },
      "service": { "type": "keyword" },
      "message": { "type": "text" },
      "context": { "type": "object" },
      "error.message": { "type": "text" },
      "error.stack": { "type": "text" }
    }
  }
}
 
// Platform Index Pattern
{
  "index_patterns": ["platform-logs-*"],
  "mappings": {
    "properties": {
      "timestamp": { "type": "date" },
      "level": { "type": "keyword" },
      "service": { "type": "keyword" },
      "message": { "type": "text" },
      "context": { "type": "object" },
      "error.message": { "type": "text" },
      "error.stack": { "type": "text" }
    }
  }
}

4. Verify Log Collection

# Check OpenSearch receiving logs
curl -u admin:password http://opensearch:9200/_cat/indices?v | grep logs
 
# Query recent logs
curl -u admin:password -X GET "http://opensearch:9200/discord-bot-logs-*/_search?size=10&sort=timestamp:desc"
 
# Check log count by service
curl -u admin:password -X GET "http://opensearch:9200/logs-*/_search" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "by_service": {
      "terms": { "field": "service" }
    }
  }
}'

5. OpenSearch Dashboards

Create visualization dashboards:

  • Error Rate: Line chart of error logs over time
  • Response Times: Histogram of API response times from context
  • Authentication Metrics: Login success/failure rates
  • Service Health: Status checks and uptime metrics

Environment Variables for OpenSearch:

# OpenSearch Configuration
OPENSEARCH_HOST=opensearch.natca.org
OPENSEARCH_PORT=9200
OPENSEARCH_USER=admin
OPENSEARCH_PASSWORD=secure_password
OPENSEARCH_INDEX_PREFIX=mynatca-logs

Common Deployment Commands (Updated October 2025)

Platform Commands

Data Synchronization:

# Full production sync (all tables in correct dependency order)
node sync/sync-all.js --env=prod
 
# Individual table sync with dependencies (syncs base tables first)
node sync/sync-all.js positions --env=prod
node sync/sync-all.js members --env=prod
node sync/sync-all.js teams --env=prod
 
# Fast re-sync without dependencies (New October 2025)
# Use after initial full sync when only specific table needs updating
node sync/sync-all.js positions --skip-deps --env=prod
node sync/sync-all.js members --skip-deps --env=prod
 
# View sync help and options
node sync/sync-all.js --help

Development Sync:

# Sync to dev schema (default)
node sync/sync-all.js
 
# Individual table sync to dev
node sync/sync-all.js positions
node sync/sync-all.js members
node sync/sync-all.js teams
 
# Fast re-sync to dev without dependencies
node sync/sync-all.js positions --skip-deps

Sync Command Improvements (October 2025):

  1. Environment-aware positions sync: Now correctly syncs to public schema with --env=prod
  2. Skip dependencies flag: New --skip-deps option for faster re-syncs
  3. Schema logging: All syncs now log target schema for verification
  4. Consistent pattern: All sync scripts follow same environment detection pattern

Discord Bot Commands

Testing:

# Run command test suite
npm test
 
# Run tests with detailed output
npm run test:verbose

Deployment:

# Deploy slash commands to Discord
npm run deploy
 
# Start bot in production
npm start
 
# Start bot in development
npm run dev

Troubleshooting

Common Issues

Data Sync Issues

Sync Targeting Wrong Schema:

# Symptom: Production sync writes to dev schema
# Solution: Verify script respects --env=prod flag
 
# Check sync output for schema confirmation
node sync/sync-all.js positions --env=prod
# Should show: "🎯 Syncing to public schema"

Missing Columns or Constraints:

# Symptom: Sync fails with "column does not exist"
# Solution: Run required migrations first
 
# Check if migrations needed
psql -c "\d public.positions"
 
# Run migrations
psql -f migrations/add_positions_enddate.sql
psql -f migrations/add_positions_unique_constraint.sql

Foreign Key Constraint Failures:

# Symptom: Sync fails with foreign key violation
# Solution: Sync base tables first or use full sync
 
# Wrong: Syncing dependent table first
node sync/sync-all.js positions --skip-deps --env=prod  # Fails if members not synced
 
# Correct: Full sync respects dependencies
node sync/sync-all.js --env=prod  # Syncs in correct order

Discord Bot Issues

Commands Not Working for Staff/RNAV:

# Symptom: /status fails for Staff (membertypeid=8) or RNAV (membertypeid=10)
# Solution: Verify query includes all member types
 
# Correct query should use .in('membertypeid', [6, 8, 10])
# Not .eq('membertypeid', 6)

Test Suite Failures:

# Run tests with verbose output
npm run test:verbose
 
# Check for missing mock data
# Verify test-commands.js has Staff and RNAV test cases

Function Timeout

// Increase timeout in vercel.json
{
  "functions": {
    "pages/api/sync/**/*.js": {
      "maxDuration": 300
    }
  }
}

Environment Variable Issues

# Check environment variables
vercel env ls
 
# Pull environment variables locally
vercel env pull .env.local
 
# Add missing variables
vercel env add VARIABLE_NAME

Build Failures

# Check build logs
vercel logs <deployment-url>
 
# Debug locally
vercel dev
 
# Clear build cache
vercel --force

This comprehensive Vercel deployment guide ensures reliable, scalable deployment of the MyNATCA platform with proper monitoring, security, and performance optimization.