// ⚠️ CRITICAL: Import config FIRST to load .env before other modules import { config } from './config.js'; import path from 'node:path'; import http from 'node:http'; import { fileURLToPath } from 'node:url'; import express from 'express'; import { Server as SocketIOServer } from 'socket.io'; import cors from 'cors'; import helmet from 'helmet'; import cookieParser from 'cookie-parser'; // Security & Logging (ADR-015) import { globalLimiter, authLimiter, codeExecutionLimiter } from './middleware/rateLimiter.js'; import { errorHandler, notFoundHandler } from './middleware/errorHandler.js'; import { createCorsOriginHandler } from './middleware/corsConfig.js'; // ADR-064: Strict CORS import { logger, requestLogger, apiLogger } from './utils/logger.js'; // ADR-036: Swagger/OpenAPI Documentation import swaggerJsdoc from 'swagger-jsdoc'; import swaggerUi from 'swagger-ui-express'; import { swaggerOptions } from './swagger.config.js'; // v0.003.001 - Clean v3 Architecture + Security Fixes (ADR-021) // v2 legacy removed — all routes now in v3 import authRoutesV3 from './routes/v3/auth.js'; import spacesRoutesV3 from './routes/v3/spaces.js'; import projectsRoutesV3 from './routes/v3/projects.js'; import tablesRoutesV3 from './routes/v3/tables.js'; import columnsRoutesV3 from './routes/v3/columns.js'; // ADR-019: Separated columns import rowsRoutesV3 from './routes/v3/rows.js'; // ADR-019: Separated rows (bulk operations) import widgetRoutesV3 from './routes/v3/widgets.js'; import { mountModuleRoutes } from './modules/loader.js'; // MODULE-CONTRACT v1: autonomous-module route registry (replaces static per-module imports, e.g. ADR-165 SC-SIM) import dataSourcesRoutesV3 from './routes/v3/data-sources.js'; import filesRoutesV3 from './routes/v3/files.js'; import webhooksRoutesV3 from './routes/v3/webhooks.js'; import apiKeysRoutesV3 from './routes/v3/api-keys.js'; import aiAgentsRoutesV3 from './routes/v3/ai-agents.js'; import foldersRoutesV3 from './routes/v3/folders.js'; import batchRoutesV3 from './routes/v3/batch.js'; import schemaRoutesV3 from './routes/v3/schema.js'; import userSettingsRoutesV3 from './routes/v3/user-settings.js'; import documentsRoutesV3 from './routes/v3/documents.js'; import systemRoutesV3 from './routes/v3/system.js'; import exportImportRoutesV3 from './routes/v3/export-import.js'; // ADR-020: Export/Import import agentUsersRoutesV3 from './routes/v3/agent-users.js'; // ADR-023: Agent-as-User import errorPagesRoutes from './routes/error-pages/index.js'; import testDoomRoutes from './routes/test-doom.js'; import chatRoutesV3 from './routes/v3/chat.js'; // ADR-024: Chat & Message Architecture import fitnessRoutesV3 from './routes/v3/fitness.js'; // ADR-025: Fitness Module import wellnessRoutesV3 from './routes/v3/wellness.js'; // ADR-027: Wellness Ecosystem import codeRoutesV3 from './routes/v3/code.js'; // ADR-032: Code Execution Engine import terminalRoutesV3 from './routes/v3/terminal.js'; // ADR-024: OpenCode Terminal Agent import labsRoutesV3 from './routes/v3/labs.js'; // ADR-043: MindWorkflow Integration import columnMappingRoutesV3 from './routes/v3/column-mapping.js'; // ADR-069: Column Mapping import widgetLibraryRoutesV3 from './routes/v3/widget-library.js'; // ADR-073: Widget Picker System import ticketsRoutesV3 from './routes/v3/tickets.js'; // ADR-098: Ticket Status API import agentVersionsRoutesV3 from './routes/v3/agent-versions.js'; // ADR-0007-S: G1-data agent_versions write path import telegramRoutesV3 from './routes/v3/telegram.js'; // ADR-098: Telegram Bot integration import telegramNikitronRoutes from './routes/v3/telegramNikitron.js'; // NikitronBot: Telegram bot for Nikitron import oauthRoutes from './routes/oauth/index.js'; // ADR-063: OIDC Provider for WorkAdventure import waRoutesV3 from './routes/v3/wa/index.js'; // ADR-063: WorkAdventure Admin API import calendarRoutesV3 from './routes/v3/calendar.js'; // Google Calendar Integration import frameRoutesV3 from './routes/v3/frame.js'; // Brilliant Frame Smart Glasses Integration import deviceLogsRoutesV3 from './routes/v3/device-logs.js'; // BLE Device Debug Logs import { startCalendarSync } from './services/CalendarSyncScheduler.js'; // Google Calendar Scheduler import scheduleTriggerService from './services/ScheduleTriggerService.js'; // Schedule-based automation triggers import lifePipelineRoutesV3 from './routes/v3/life-pipeline.js'; // Life Pipeline: Morning Briefing, Evening Check-in import contentPipelineRoutesV3 from './routes/v3/content-pipeline.js'; // Content Pipeline: AI/Tech News Aggregation import publicRoutesV3 from './routes/v3/public.js'; // ADR-105: Public Space Access (no auth) // NO-SIGNUP-MCP §B1: friendly-path alias for the per-space public MCP mount so // the shipped `godcrm.ai/s/help/mcp` URL resolves at the app level (the // canonical mount is `/api/v3/public/s/:slug/mcp` on publicRoutesV3). import { publicAbuseGuard, publicRateLimit, publicSpaceAccess } from './middleware/publicAccess.js'; import { mcpPublicHandler } from './services/mcp/publicMcp.js'; import screenshotsRoutesV3 from './routes/v3/screenshots.js'; // Screenshot Service for Telegram posts import pesRoutesV3 from './routes/v3/pes.js'; // PES ↔ CRM Bridge import pesAppRoutes from './routes/v3/pes/appRoutes.js'; // PES Mini App (public) import pluginRoutesV3 from './routes/v3/plugin.js'; // Plugin API (Photoshop, etc.) import bddRoutesV3 from './routes/v3/bdd.js'; // ADR-156 Phase 5A: BDD test runs import connectorsAuthedRouter, { connectorsCallbackRouter } from './routes/v3/connectors.js'; // ADR-0028 Phase 1: Space Connectors import mailRoutesV3 from './routes/v3/mail.js'; // ADR-160: Mail module (IMAP/SMTP bridge) import credentialVault from './services/connectors/CredentialVault.js'; // ADR-0028 Phase 1: vault lifecycle import adminChatNotificationsRoutesV3 from './routes/v3/admin/chatNotifications.js'; // ADR-0064 WP-A: global default chat notification prefs import { startInvalidationListener as startChatPrefsListener } from './services/notifications/resolveChatPrefs.js'; // ADR-0064 WP-A: cluster-wide cache eviction import { startInflightBus } from './services/inflight/notifyBus.js'; // ADR-0057-A WP-B: chat_inflight LISTEN bus import ownerRoutesV3 from './routes/v3/owner.js'; // ADR-0059 AMEND-3 §4.9: owner calls settings import permissionResolver from './services/agent-permissions/resolver.js'; // ADR-0053 Phase C2: command-policy resolver import agentPermissionsRoutesV3 from './routes/v3/agent-permissions.js'; // ADR-0053 Phase C2: PreToolUse hook endpoint import secretsVault from './services/secrets/SecretsVault.js'; // ADR-0040 Phase 0: owner secrets vault import secretsRoutesV3 from './routes/v3/secrets.js'; // ADR-0040 Phase 1: owner secrets CRUD + reveal import auditRoutesV3 from './routes/v3/audit.js'; // ADR-0066-A §C: owner-only audit chain verify import { getAdapter as getDbAdapter } from './database/connection.js'; // ADR-0040/ADR-0053: vault + resolver DB binding import agentRunDispatcherAdminRouter from './routes/v3/agentRunDispatcher.js'; // ADR-0030 Phase 2: dispatcher admin API import { authenticate } from './middleware/auth.js'; import { requestContext } from './middleware/requestContext.js'; // ADR-0066 P0: req.requestId/spaceId/actingAs import { uploadsFileGuard, downloadsFileGuard } from './middleware/fileGuard.js'; // ADR-0016: Authenticated file delivery import { dbGet } from './database/connection.js'; // ADR-064: Health check DB ping // Monitoring service (self-hosted) import { createMonitoringRouter } from './services/MonitoringService.js'; // Routes moved from v2 to v3 (still used on v3 endpoints) import automationsRoutes from './routes/v3/automations.js'; import formConfigsRoutes from './routes/v3/form-configs.js'; import accessRoutes from './routes/v3/access.js'; const app = express(); // Trust first proxy (nginx) — required for express-rate-limit behind reverse proxy app.set('trust proxy', 1); const PORT = config.PORT; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const clientDistPath = path.resolve(__dirname, '../dist'); // Middleware // CSP must allow WebAssembly instantiation (pixi/transcoder WASM modules). // helmet()'s default script-src is 'self' only, which throws // "WebAssembly.instantiate(): ... 'unsafe-eval' is not an allowed source" // in Safari/Chrome. 'wasm-unsafe-eval' enables WASM compile without the // full 'unsafe-eval' relaxation. Directives mirror deploy/nginx/godcrm.conf. app.use( helmet({ contentSecurityPolicy: { useDefaults: true, directives: { 'default-src': ["'self'"], 'script-src': ["'self'", "'unsafe-inline'", "'unsafe-eval'", "'wasm-unsafe-eval'"], // mirror deploy/nginx/godcrm.conf: marketing landing (godcrm.ai) pulls // Google Fonts (fonts.googleapis.com CSS + fonts.gstatic.com files) and // embeds YouTube. Without https: in style/font-src the stylesheet is // refused and the landing falls back to system fonts. 'style-src': ["'self'", 'https:', "'unsafe-inline'"], 'img-src': ["'self'", 'data:', 'blob:'], 'font-src': ["'self'", 'https:', 'data:'], 'connect-src': ["'self'", 'wss:', 'https:'], 'frame-src': ['https://www.youtube-nocookie.com', 'https://www.youtube.com'] } } }) ); // ADR-176: the embed loader + chat iframe are deliberately cross-origin — they // are dropped into third-party sites (e.g. the Penpot clone at design-test.godcrm.ai). // helmet's default Cross-Origin-Resource-Policy: same-origin makes the browser // block the cross-origin