/** * ChronoMind Backend — Fastify server entry point. * * Product-specific service for timers, routines, households, shared timers. * Common platform features (auth, billing, flags, etc.) come from platform-service. * Port: 4011 (configurable via PORT env var). */ import { createServiceApp, registerOptionalJwtContext, startService } from '@bytelyst/fastify-core'; import { timerRoutes } from './modules/timers/routes.js'; import { routineRoutes } from './modules/routines/routes.js'; import { householdRoutes } from './modules/households/routes.js'; import { sharedTimerRoutes } from './modules/shared-timers/routes.js'; import { webhookRoutes } from './modules/webhooks/routes.js'; import { initCosmosIfNeeded } from './lib/cosmos-init.js'; import { initDatastore } from './lib/datastore.js'; import { config } from './lib/config.js'; import { getAllFlags } from './lib/feature-flags.js'; import { getBufferedEvents, flushEvents } from './lib/telemetry.js'; import { jwtVerify } from 'jose'; import type { JwtPayload } from './lib/request-context.js'; const jwtSecret = new TextEncoder().encode(config.JWT_SECRET); await initCosmosIfNeeded(); initDatastore(); const app = await createServiceApp({ name: 'chronomind-backend', version: '0.1.0', description: 'ChronoMind product-specific backend — timers, routines, households, shared timers, webhooks', corsOrigin: config.CORS_ORIGIN, swagger: { title: 'ChronoMind Backend', description: 'Timers, routines, households, shared timers, webhooks', port: config.PORT, }, metrics: true, }); await registerOptionalJwtContext(app, { verifyToken: async (token: string) => { const { payload } = await jwtVerify(token, jwtSecret, { issuer: 'bytelyst-platform' }); return payload as unknown as JwtPayload; }, }); await app.register(timerRoutes, { prefix: '/api' }); await app.register(routineRoutes, { prefix: '/api' }); await app.register(householdRoutes, { prefix: '/api' }); await app.register(sharedTimerRoutes, { prefix: '/api' }); await app.register(webhookRoutes, { prefix: '/api' }); // ── Diagnostics routes (no auth) ──────────────────────────────── app.get('/api/diagnostics/flags', async () => getAllFlags()); app.get('/api/diagnostics/telemetry', async () => ({ events: getBufferedEvents() })); app.post('/api/diagnostics/telemetry/flush', async () => ({ flushed: flushEvents().length })); await startService(app, { port: config.PORT, host: config.HOST });