fix(api): fix RLS context, DTO validation, and error handling

- Wrap SET LOCAL in transactions for proper connection pooling
- Make workspaceId optional in query DTOs (derived from guards)
- Replace Error throws with UnauthorizedException in activity controller
- Update workspace guard to remove RLS context setting
- Document that services should use withUserContext/withUserTransaction
This commit is contained in:
Jason Woltje
2026-01-29 20:14:27 -06:00
parent 95833fb4ea
commit 26a0df835f
9 changed files with 63 additions and 50 deletions

View File

@@ -7,13 +7,11 @@ import {
Logger,
} from "@nestjs/common";
import { PrismaService } from "../../prisma/prisma.service";
import { setCurrentUser } from "../../lib/db-context";
/**
* WorkspaceGuard ensures that:
* 1. A workspace is specified in the request (header, param, or body)
* 2. The authenticated user is a member of that workspace
* 3. The user context is set for Row-Level Security (RLS)
*
* This guard should be used in combination with AuthGuard:
*
@@ -25,7 +23,7 @@ import { setCurrentUser } from "../../lib/db-context";
* @Get()
* async getTasks(@Workspace() workspaceId: string) {
* // workspaceId is verified and available
* // RLS context is automatically set
* // Service layer must use withUserContext() for RLS
* }
* }
* ```
@@ -36,6 +34,9 @@ import { setCurrentUser } from "../../lib/db-context";
* - Request body: `workspaceId` field
*
* Priority: Header > Param > Body
*
* Note: RLS context must be set at the service layer using withUserContext()
* or withUserTransaction() to ensure proper transaction scoping with connection pooling.
*/
@Injectable()
export class WorkspaceGuard implements CanActivate {
@@ -75,9 +76,6 @@ export class WorkspaceGuard implements CanActivate {
);
}
// Set RLS context for this request
await setCurrentUser(user.id, this.prisma);
// Attach workspace info to request for convenience
request.workspace = {
id: workspaceId,