diff --git a/apps/api/src/common/controllers/csrf.controller.ts b/apps/api/src/common/controllers/csrf.controller.ts index 8c21045..8865ae9 100644 --- a/apps/api/src/common/controllers/csrf.controller.ts +++ b/apps/api/src/common/controllers/csrf.controller.ts @@ -16,7 +16,7 @@ interface AuthenticatedRequest extends Request { user?: AuthenticatedUser; } -@Controller("api/v1/csrf") +@Controller("v1/csrf") export class CsrfController { constructor(private readonly csrfService: CsrfService) {} diff --git a/apps/api/src/federation/command.controller.ts b/apps/api/src/federation/command.controller.ts index 4ec68a3..400198f 100644 --- a/apps/api/src/federation/command.controller.ts +++ b/apps/api/src/federation/command.controller.ts @@ -12,7 +12,7 @@ import type { AuthenticatedRequest } from "../common/types/user.types"; import type { CommandMessageDetails, CommandResponse } from "./types/message.types"; import type { FederationMessageStatus } from "@prisma/client"; -@Controller("api/v1/federation") +@Controller("v1/federation") export class CommandController { private readonly logger = new Logger(CommandController.name); diff --git a/apps/api/src/federation/event.controller.ts b/apps/api/src/federation/event.controller.ts index 99b5b40..282c67f 100644 --- a/apps/api/src/federation/event.controller.ts +++ b/apps/api/src/federation/event.controller.ts @@ -23,7 +23,7 @@ import { IncomingEventAckDto, } from "./dto/event.dto"; -@Controller("api/v1/federation") +@Controller("v1/federation") export class EventController { private readonly logger = new Logger(EventController.name); diff --git a/apps/api/src/federation/federation-auth.controller.ts b/apps/api/src/federation/federation-auth.controller.ts index 9f9d2bf..639ceac 100644 --- a/apps/api/src/federation/federation-auth.controller.ts +++ b/apps/api/src/federation/federation-auth.controller.ts @@ -18,7 +18,7 @@ import { ValidateFederatedTokenDto, } from "./dto/federated-auth.dto"; -@Controller("api/v1/federation/auth") +@Controller("v1/federation/auth") export class FederationAuthController { private readonly logger = new Logger(FederationAuthController.name); diff --git a/apps/api/src/federation/federation.controller.ts b/apps/api/src/federation/federation.controller.ts index 674d65a..99bc796 100644 --- a/apps/api/src/federation/federation.controller.ts +++ b/apps/api/src/federation/federation.controller.ts @@ -27,7 +27,7 @@ import { } from "./dto/connection.dto"; import { FederationConnectionStatus } from "@prisma/client"; -@Controller("api/v1/federation") +@Controller("v1/federation") export class FederationController { private readonly logger = new Logger(FederationController.name); diff --git a/apps/api/src/federation/query.controller.ts b/apps/api/src/federation/query.controller.ts index 4e80ef6..2afc86f 100644 --- a/apps/api/src/federation/query.controller.ts +++ b/apps/api/src/federation/query.controller.ts @@ -12,7 +12,7 @@ import type { AuthenticatedRequest } from "../common/types/user.types"; import type { QueryMessageDetails, QueryResponse } from "./types/message.types"; import type { FederationMessageStatus } from "@prisma/client"; -@Controller("api/v1/federation") +@Controller("v1/federation") export class QueryController { private readonly logger = new Logger(QueryController.name); diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index 647f5bd..55dafa1 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -1,5 +1,5 @@ import { NestFactory } from "@nestjs/core"; -import { ValidationPipe } from "@nestjs/common"; +import { RequestMethod, ValidationPipe } from "@nestjs/common"; import cookieParser from "cookie-parser"; import { AppModule } from "./app.module"; import { getTrustedOrigins } from "./auth/auth.config"; @@ -47,6 +47,16 @@ async function bootstrap() { app.useGlobalFilters(new GlobalExceptionFilter()); + // Set global API prefix — all routes get /api/* except auth and health + // Auth routes are excluded because BetterAuth expects /auth/* paths + // Health is excluded because Docker healthchecks hit /health directly + app.setGlobalPrefix("api", { + exclude: [ + { path: "health", method: RequestMethod.GET }, + { path: "auth/(.*)", method: RequestMethod.ALL }, + ], + }); + // Configure CORS for cookie-based authentication // Origin list is shared with BetterAuth trustedOrigins via getTrustedOrigins() const trustedOrigins = getTrustedOrigins();