Platform
Platform Overview

Platform Technical Overview

The MyNATCA Platform is an Express.js-based backend service that provides authentication, API proxying, data synchronization, and session management for the entire MyNATCA ecosystem.

Architecture

The Platform serves as the central integration hub, connecting:

  • Discord Bot: Member verification and role management
  • Member Hub: Frontend application for member self-service
  • MyNATCA API: Legacy member data system
  • Supabase: Modern PostgreSQL database
  • Auth0: Authentication and identity management
  • Redis: Session storage and caching
  • Rackspace Email: Professional @natca.net email provisioning
  • Intercom: Customer support and member communication

Key Features

Authentication Services

  • OAuth 2.0 authentication with Auth0
  • Session management with Redis
  • JWT token handling (idToken for API forwarding, accessToken for Auth0 Management API)
  • Secure cookie configuration with trust proxy support

API Proxy Gateway

  • Dynamic proxy middleware for external API integration
  • Automatic Bearer token forwarding
  • CORS configuration
  • Path rewriting and request/response transformation

Data Synchronization

  • MySQL to Supabase sync for member data
  • Scheduled batch processing
  • Error handling and retry logic
  • Sync health monitoring

External Service Integrations

  • Rackspace Email: Create and manage @natca.net email addresses for members
  • Intercom: Sync member data for customer support operations
  • Webhook handlers for real-time updates
  • Secure API authentication and credential management

Session Management

  • Redis-backed Express sessions
  • Trust proxy configuration for reverse proxy deployments
  • Cross-subdomain session support
  • Secure cookie handling (HttpOnly, Secure, SameSite)

Recent Updates (October 2025)

JSON Logging System

Replaced all console.log calls with structured JSON logging for OpenSearch compatibility:

  • Clean JSON output without emoji or unstructured text
  • Timestamp, level, service, message, and context fields
  • Full stack traces for errors
  • OpenSearch-ready format

Trust Proxy Configuration

Added critical app.set('trust proxy', 1) configuration:

  • Required for deployment behind reverse proxies (Digital Ocean, nginx)
  • Fixes session persistence issues on production
  • Enables secure cookies with HTTPS recognition

Session Persistence Fixes

Resolved session not persisting after Auth0 login:

  • Trust proxy configuration enables secure cookie setting
  • Redis reconnection strategy for reliability
  • Rolling session refresh on each request

Configuration

Required Environment Variables

# Server
PORT=1300
NODE_ENV=production
 
# Database
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your_service_key
REDIS_URL=redis://redis:6379
 
# Authentication
AUTH0_DOMAIN=natca-prod.us.auth0.com
AUTH0_CLIENT_ID=your_client_id
AUTH0_CLIENT_SECRET=your_client_secret
SESSION_SECRET=your_random_secret_min_32_chars
 
# CRITICAL: Trust proxy (required for production)
TRUST_PROXY=1
 
# External Integrations
RACKSPACE_API_KEY=your_rackspace_api_key
RACKSPACE_SECRET_KEY=your_rackspace_secret_key
RACKSPACE_CUSTOMER_ID=123456
INTERCOM_ACCESS_TOKEN=your_intercom_token

Server Initialization

// server.js
const express = require('express');
const session = require('express-session');
const RedisStore = require('connect-redis').default;
const logger = require('./lib/logger');
 
const app = express();
 
// CRITICAL: Trust proxy for reverse proxy deployments
app.set('trust proxy', 1);
 
// Session configuration
app.use(session({
  store: new RedisStore({ client: redisClient }),
  secret: process.env.SESSION_SECRET,
  name: 'platform.session',
  resave: false,
  saveUninitialized: false,
  rolling: true,
  cookie: {
    maxAge: 7 * 24 * 60 * 60 * 1000,
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax'
  }
}));
 
// JSON logging
logger.info('Platform server starting', {
  nodeEnv: process.env.NODE_ENV,
  port: process.env.PORT
});

Directory Structure

platform/
├── server.js                 # Main server entry point
├── lib/
│   ├── logger.js            # JSON structured logger
│   ├── supabase.js          # Supabase client
│   └── redis.js             # Redis client
├── routes/
│   ├── auth.js              # Authentication routes
│   ├── verify.js            # Discord verification
│   ├── sync.js              # Data synchronization
│   └── member.js            # Member management
├── middleware/
│   ├── proxy.js             # API proxy middleware
│   └── auth-check.js        # Authentication middleware
└── sync/
    ├── members.js           # Member sync logic
    ├── facilities.js        # Facility sync logic
    └── scheduler.js         # Sync scheduling

API Endpoints

Interactive Documentation: The Platform API includes comprehensive Swagger/OpenAPI documentation at http://localhost:1300/api-docs (opens in a new tab) (development). See the Platform API Reference for complete details.

Health Check

  • GET /api/health - Service health status

Authentication

  • GET /api/auth/login - Initiate OAuth flow
  • GET /api/auth/callback - OAuth callback handler
  • GET /api/auth/session - Current session status
  • GET /api/auth/logout - Logout and destroy session
  • POST /api/auth/service - Service-to-service authentication

Verification

  • POST /api/verify/start - Start Discord verification
  • GET /api/verify/complete/:id - Complete verification

Data Sync

  • POST /api/sync/trigger - Trigger data sync (accepts: members, facilities, regions, positions, all)
  • POST /api/sync/all - Trigger full sync
  • POST /api/sync/members - Sync members only
  • POST /api/sync/facilities - Sync facilities only
  • POST /api/sync/regions - Sync regions only
  • POST /api/sync/positions - Sync positions only
  • GET /api/sync/status - Get sync status (not in Swagger)
  • GET /api/sync/health - Sync health metrics (not in Swagger)

Member Management

  • GET /api/member/:memberNumber - Get member by member number
  • GET /api/member/discord/:discordId - Get member by Discord ID
  • POST /api/member/:memberNumber/link-discord - Link Discord account
  • POST /api/member/:memberNumber/unlink-discord - Unlink Discord account
  • POST /api/member/unlink - Unlink (session-authenticated)

Rackspace Email

  • POST /api/rackspace/check-availability - Check email format availability
  • POST /api/rackspace/create-email - Create @natca.net email account
  • POST /api/rackspace/reset-password - Reset email password

Monitoring and Observability

JSON Structured Logging

All operations logged as structured JSON:

{
  "timestamp": "2025-10-01T12:00:00.000Z",
  "level": "info",
  "service": "platform",
  "message": "User authenticated successfully",
  "context": {
    "userId": "auth0|123456",
    "memberNumber": "12345"
  }
}

OpenSearch Integration

  • Logs shipped to OpenSearch via Filebeat or Fluentd
  • Index patterns: platform-logs-YYYY.MM.DD
  • Visualization dashboards for error rates, response times, authentication metrics

Health Checks

# Platform health
curl https://platform.natca.org/api/health
 
# Session health
curl https://platform.natca.org/api/health/session
 
# Sync health
curl https://platform.natca.org/api/sync/health

Deployment

Digital Ocean App Platform

# .do/app.yaml
services:
  - name: platform
    source_dir: /
    environment_slug: node-js
    instance_count: 2
    http_port: 1300
    envs:
      - key: NODE_ENV
        value: production
      - key: TRUST_PROXY
        value: "1"
      - key: SESSION_SECRET
        value: ${SESSION_SECRET}
        type: SECRET

Docker Deployment

# Dockerfile
FROM node:18-alpine
 
WORKDIR /app
 
COPY package*.json ./
RUN npm ci --production
 
COPY . .
 
EXPOSE 1300
 
CMD ["node", "server.js"]
# docker-compose.yml
services:
  platform:
    build: .
    ports:
      - "1300:1300"
    environment:
      - NODE_ENV=production
      - TRUST_PROXY=1
      - REDIS_URL=redis://redis:6379
    depends_on:
      - redis
 
  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data

Security Considerations

Session Security

  • HttpOnly cookies prevent XSS attacks
  • Secure flag ensures HTTPS-only transmission
  • SameSite protection against CSRF
  • Redis-backed storage for distributed sessions

Trust Proxy Configuration

  • Only trust first proxy in chain
  • Validate X-Forwarded-* headers
  • Different configuration per environment

Environment Secrets

  • Strong random SESSION_SECRET (32+ characters)
  • Different secrets per environment
  • Secrets stored securely (not in code)

Troubleshooting

Sessions Not Persisting

Problem: Users logged out immediately after authentication Solution: Enable trust proxy: app.set('trust proxy', 1)

Redis Connection Failures

Problem: Intermittent session errors Solution: Implement reconnection strategy with exponential backoff

Proxy Middleware Errors

Problem: API requests fail with 502 errors Solution: Verify target URL and Bearer token forwarding

Related Documentation


The Platform is the backbone of the MyNATCA ecosystem, providing secure authentication, reliable session management, and seamless integration between all ecosystem components.