From b8e7dbccc6ac644dbfb039eca83f841799e45ae9 Mon Sep 17 00:00:00 2001 From: jubnl Date: Tue, 22 Sep 2026 12:32:17 +0200 Subject: [PATCH] fix(server): boot-time settings read runs inside an explicit ORM request context --- server/src/bootstrap.ts | 6 +++++- server/src/nest/database/request-context.ts | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/server/src/bootstrap.ts b/server/src/bootstrap.ts index d68fd93a6..66690d8b1 100644 --- a/server/src/bootstrap.ts +++ b/server/src/bootstrap.ts @@ -13,6 +13,7 @@ import { TrekWsAdapter } from './nest/realtime/trek-ws.adapter'; import { SettingsService } from './nest/settings/settings.service'; import { StorageService } from './nest/storage/storage.service'; import { MikroORM } from '@mikro-orm/core'; +import { withRequestContext } from './nest/database/request-context'; import type { INestApplication } from '@nestjs/common'; import type { ConfigType } from '@nestjs/config'; import { NestFactory } from '@nestjs/core'; @@ -101,7 +102,10 @@ export async function buildApp(): Promise { // engines go through the same door — the second one answers the avoidance questions // the first cannot, and is blocked just as silently when the policy leaves it out. const settings = app.get(SettingsService, { strict: false }); - const defaults = await settings?.getAdminUserDefaults(); + // Boot runs outside any HTTP request, so there is no per-request EntityManager + // yet and `allowGlobalContext` is off in production: every repository-backed + // read at boot goes through D6's explicit context (see request-context.ts). + const defaults = await withRequestContext(orm, () => settings?.getAdminUserDefaults()); const asUrl = (value: unknown) => (typeof value === 'string' ? value : null); applyGlobalMiddleware(instance, { http, diff --git a/server/src/nest/database/request-context.ts b/server/src/nest/database/request-context.ts index 9987519a8..a982fdd88 100644 --- a/server/src/nest/database/request-context.ts +++ b/server/src/nest/database/request-context.ts @@ -1,4 +1,4 @@ -import { RequestContext, type MikroORM } from '@mikro-orm/core'; +import { RequestContext, type EntityManager } from '@mikro-orm/core'; /** * A request-scoped EntityManager for work that no HTTP request wraps. @@ -11,6 +11,7 @@ import { RequestContext, type MikroORM } from '@mikro-orm/core'; * call. It is deliberately a function and not a decorator so a call site can * pass the ORM it was given rather than reach for a global. */ -export function withRequestContext(orm: MikroORM, fn: () => T): T { +/** Accepts anything carrying the ORM's global EntityManager (MikroORM itself, or a narrower handle); `app.get(MikroORM)`'s readonly-entities generic would otherwise not assign to `MikroORM`. */ +export function withRequestContext(orm: { em: EntityManager }, fn: () => T): T { return RequestContext.create(orm.em, fn); }