From 65128db7133338c81b80e19048b5203ffd054189 Mon Sep 17 00:00:00 2001
From: patrick-motsch
Date: Fri, 13 Feb 2026 17:26:56 +0100
Subject: [PATCH] fix: use original session user for bridge callbacks instead
of system user (RBAC)
Co-authored-by: Cursor
---
.../features/teamsbot/routeFeatureTeamsbot.py | 32 ++++++++++++++++---
1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/modules/features/teamsbot/routeFeatureTeamsbot.py b/modules/features/teamsbot/routeFeatureTeamsbot.py
index 19d495a5..9821fc6c 100644
--- a/modules/features/teamsbot/routeFeatureTeamsbot.py
+++ b/modules/features/teamsbot/routeFeatureTeamsbot.py
@@ -363,11 +363,22 @@ async def bridgeStatusCallback(
logger.info(f"Bridge status callback: session={sessionId}, status={status}")
try:
- # Update session status (bridge callbacks have no user context)
+ # Load the original user who started the session (has RBAC roles in mandate)
from modules.datamodels.datamodelUam import User
+ from modules.interfaces.interfaceDbApp import getRootInterface
+
systemUser = User(id="system", username="system", email="system@poweron.swiss")
interface = interfaceDb.getInterface(systemUser, featureInstanceId=instanceId)
+ # Look up original user from session for consistent context
+ session = interface.getSession(sessionId)
+ startedByUserId = session.get("startedByUserId") if session else None
+ if startedByUserId:
+ rootInterface = getRootInterface()
+ originalUser = rootInterface.getUser(startedByUserId)
+ if originalUser:
+ interface = interfaceDb.getInterface(originalUser, featureInstanceId=instanceId)
+
updates = {"status": status}
if errorMessage:
updates["errorMessage"] = errorMessage
@@ -411,16 +422,27 @@ async def bridgeAudioWebsocket(
config = _getInstanceConfig(instanceId)
logger.info(f"Bridge audio WebSocket config loaded: session={sessionId}")
+ # Load the original user who started the session (has RBAC roles in mandate)
+ # Bridge callbacks have no HTTP auth, so we reconstruct the user context from the session record.
from modules.datamodels.datamodelUam import User
- systemUser = User(id="system", username="system", email="system@poweron.swiss")
+ from modules.interfaces.interfaceDbApp import getRootInterface
- # Look up mandateId from the session record (needed for AI billing context)
+ systemUser = User(id="system", username="system", email="system@poweron.swiss")
sessionInterface = interfaceDb.getInterface(systemUser, featureInstanceId=instanceId)
session = sessionInterface.getSession(sessionId)
mandateId = session.get("mandateId") if session else None
+ startedByUserId = session.get("startedByUserId") if session else None
- service = TeamsbotService(systemUser, mandateId, instanceId, config)
- logger.info(f"Bridge audio WebSocket service created: session={sessionId}, mandateId={mandateId}")
+ # Look up the original user (getRootInterface uses admin context, can load any user)
+ rootInterface = getRootInterface()
+ originalUser = rootInterface.getUser(startedByUserId) if startedByUserId else None
+
+ if not originalUser:
+ logger.warning(f"Could not load original user {startedByUserId}, falling back to system user")
+ originalUser = systemUser
+
+ service = TeamsbotService(originalUser, mandateId, instanceId, config)
+ logger.info(f"Bridge audio WebSocket service created: session={sessionId}, mandateId={mandateId}, user={originalUser.id}")
await service.handleAudioStream(websocket, sessionId)
except WebSocketDisconnect: