From 7524c4d29e58b2b482abbaeba956d74bb5959d5c Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Sun, 15 Feb 2026 21:30:03 -0800 Subject: [PATCH] feat(platform-service): add GET /settings/kill-switch public endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - No auth required — mobile apps call this at launch before login - Reads kill_switch feature flag from Cosmos DB - If flag enabled=true → returns disabled:true with maintenance message - Fail-open: DB errors allow app to run normally - Response: { enabled: bool, disabled: bool, message: string } Used by iOS KillSwitchService.swift and Android KillSwitchService.kt --- .../src/modules/settings/routes.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/services/platform-service/src/modules/settings/routes.ts b/services/platform-service/src/modules/settings/routes.ts index afb4f5fb..36b3ebe9 100644 --- a/services/platform-service/src/modules/settings/routes.ts +++ b/services/platform-service/src/modules/settings/routes.ts @@ -1,6 +1,7 @@ /** * User settings REST endpoints. * + * GET /settings/kill-switch — public kill switch check (no auth) * GET /settings — get user settings * PUT /settings — merge global settings * GET /settings/device/:deviceId — get resolved settings for a device @@ -13,6 +14,7 @@ import { getRequestProductId } from '../../lib/request-context.js'; import { BadRequestError, UnauthorizedError } from '../../lib/errors.js'; import * as repo from './repository.js'; import { UpdateSettingsSchema, SetDeviceOverridesSchema, type UserSettingsDoc } from './types.js'; +import * as flagRepo from '../flags/repository.js'; function getRequestUserId(req: FastifyRequest): string { const userId = req.jwtPayload?.sub; @@ -34,6 +36,32 @@ function buildDefaultDoc(productId: string, userId: string): UserSettingsDoc { } export async function settingsRoutes(app: FastifyInstance) { + // Public kill switch endpoint — no auth required. + // Mobile apps call this at launch to check if the app is disabled. + // Reads the `kill_switch` feature flag: if enabled=true → app is disabled. + app.get('/settings/kill-switch', async req => { + const productId = + (req.query as { productId?: string }).productId || + (req.headers['x-product-id'] as string) || + process.env.PRODUCT_ID || + ''; + if (!productId) return { enabled: true, disabled: false, message: '' }; + + try { + const flag = await flagRepo.getByKey('kill_switch', productId); + if (flag && flag.enabled) { + return { + enabled: false, + disabled: true, + message: flag.description || 'LysnrAI is temporarily unavailable for maintenance.', + }; + } + } catch { + // DB error — fail open (allow app to run) + } + return { enabled: true, disabled: false, message: '' }; + }); + app.get('/settings', async req => { const productId = getRequestProductId(req); const userId = getRequestUserId(req);