From 3934612bc5ca23edab5f2aeb24a9eb8b0745f277 Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Tue, 12 May 2026 21:31:27 +0200
Subject: [PATCH] teamsbot auth fixes
---
b-reference/teams-bot/architecture.md | 20 ++++++++++++--------
c-work/_CHANGELOG.md | 2 ++
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/b-reference/teams-bot/architecture.md b/b-reference/teams-bot/architecture.md
index a7e3ef9..1939f1c 100644
--- a/b-reference/teams-bot/architecture.md
+++ b/b-reference/teams-bot/architecture.md
@@ -103,29 +103,33 @@ Refs: `service-teams-browser-bot/src/bot/audioCaptureProcedure.ts` (`__audioCapt
### Chat-Panel-Toggle-Auswahl im Auth-Layout
-Im authentifizierten Full-Teams-Layout existieren ZWEI sichtbare Buttons mit "Chat" im aria-label:
+Im authentifizierten Full-Teams-Layout existieren MEHRERE sichtbare Buttons mit "Chat" im aria-label. Kritisch ist die Unterscheidung:
-1. der **echte Toggle**: UUID-id, `aria-label="Chat (Ctrl+Shift+2)"`, **`aria-pressed="true|false"`** — toggelt das Meeting-Chat-Side-Panel.
-2. ein **Schein-Toggle**: `id="chat-button"`, `aria-label="Chat"`, **kein `aria-pressed`** — vermutlich der Side-Nav-Eintrag der Chat-App; klicken hat keinerlei Wirkung auf das Meeting-Chat-Panel.
+1. der **echte Meeting-Chat-Toggle**: UUID-id, `aria-label="Chat (Ctrl+Shift+2)"`, **`aria-pressed="true|false"`** — toggelt das Meeting-Chat-Side-Panel.
+2. **Sidebar-Navigation "Chats"**: `aria-label="Chats "` (mit Leerzeichen), **hat `aria-pressed`** — klickt man diesen, navigiert der Bot **weg vom Meeting** zur Teams-Chat-Sektion. Das Meeting wird als PiP minimiert, alle PeerConnections schließen → Video/Audio bricht ab.
+3. Weitere Buttons: `More chat options` (Menü), `tab-item-com.microsoft.chattabs.*` (Tabs im Chat-Panel), `chat-join-button`, `chat-header-participant-count`.
In light-meetings (anon) existiert nur `#chat-button` und der IST der echte Toggle (light-meetings nutzt menu-button-Semantik ohne `aria-pressed`).
`_openChatPanel()` löst das so:
- Sammelt alle sichtbaren `button` / `[role=button]` / `[role=menuitem]` deren `id`/`data-tid`/`aria-label`/`title` einen der Hints `chat`/`unterhalt`/`besprechung`/`conversation` enthält (sprachunabhängig).
+- **Filtert gefährliche Buttons aus** (`isDangerousNavButton`): Sidebar-Navigation (`aria="Chats"`/`"Unterhaltungen"`), Tab-Items (`tab-item-*`), Submenu-Triggers (`More chat options`), Participant-Count, Chat-Join-Button, App-Bar-Kinder.
- **Bevorzugt Kandidaten mit `aria-pressed` ∈ {`true`,`false`}** (echte Toggle-Buttons), Fallback ist der erste passende Nicht-Toggle.
-- Trackt geklickte Buttons per `id|data-tid|aria-label`-Key und überspringt sie in den nächsten Runden — verhindert die Endlosschleife "klicke 12× denselben falschen Button" wenn der erste Pick nichts bewirkt.
+- Trackt geklickte Buttons per `id|data-tid|aria-label`-Key und überspringt sie in den nächsten Runden.
+- **Nach Toggle-Klick**: wenn `_isChatPanelOpen()` DOM-basiert fehlschlägt, prüft Fallback ob `aria-pressed` des geklickten Toggles jetzt `"true"` ist → Panel gilt als offen (auth-mode Fallback).
Refs: `service-teams-browser-bot/src/bot/chatProcedure.ts._openChatPanel`.
### Chat-Panel-Detection
-`_isChatPanelOpen()` macht **zwei** Checks am `[data-tid="calling-right-side-panel"]`-Container — keine Fallbacks:
+`_isChatPanelOpen()` macht zwei Strategie-Checks:
-1. **Existenz + echte Visibility** des Side-Pane-Containers: `offsetWidth/Height > 0 && offsetParent !== null`. Wenn das Panel zu ist, ist der Container entweder unmounted oder vom Parent auf 0×0 kollabiert.
-2. **Mode-Disambiguation per chat-spezifischen Child-Tids** innerhalb des sichtbaren Containers: `message-pane-layout`, `message-pane-body`, `chat-pane-compose-message-footer`, `message-pane-footer`, `#chat-pane-list`, `[data-app-name="chats"]`. Trennt Chat sauber von People / Info / Captions ohne Text-Lookup.
+**Strategie 1 (light-meetings + standard)**: Check am `[data-tid="calling-right-side-panel"]`-Container:
+1. **Existenz + echte Visibility**: `offsetWidth/Height > 0 && offsetParent !== null`.
+2. **Mode-Disambiguation per chat-spezifischen Child-Tids**: `message-pane-layout`, `message-pane-body`, `chat-pane-compose-message-footer`, `message-pane-footer`, `#chat-pane-list`, `[data-app-name="chats"]`.
-Frühere Iterationen hatten zwei zusätzliche Schichten (aria-pressed-Toggle + Compose-Box-Sichtbarkeit) als "Fallback für ältere Auth-Layouts". Diese sind 2026-05-12 entfernt worden — sowohl anon als auch auth nutzen denselben `calling-right-side-panel`-Container, die Fallbacks hätten nie gefeuert (oder wären redundant gewesen wenn doch). Konform zur Coding-Regel "Do not add fallback code, if not necessary".
+**Strategie 2 (auth full-Teams Fallback)**: Im vollen Teams-Web-Client existiert `calling-right-side-panel` möglicherweise nicht oder hat ein anderes Layout. Stattdessen wird geprüft ob ein Toggle-Button mit Keyboard-Shortcut im Label (`Chat (Ctrl+...)` / `Chat (Strg+...)`) `aria-pressed="true"` hat. Dies erkennt den geöffneten Zustand zuverlässig auch wenn der DOM-Container anders strukturiert ist.
#### Trapdoor: `vdi-occlusion`
diff --git a/c-work/_CHANGELOG.md b/c-work/_CHANGELOG.md
index 53b3d5b..6751002 100644
--- a/c-work/_CHANGELOG.md
+++ b/c-work/_CHANGELOG.md
@@ -280,5 +280,7 @@ Skip: reine Refactors, Formatting, Lint, Dep-Bumps, Test-only, Wiki-Tippfehler.
- 2026-05-11 | fix | service-teams-browser-bot | Chat-Scraper Root Cause: Timestamp-Separatoren ("22:01") wurden als Chat-Nachrichten erkannt weil der innerText-Fallback auch bei unbekanntem Autor griff; Fallback jetzt nur wenn Autor identifiziert wurde
- 2026-05-11 | fix | gateway | mainServiceWeb progressLogUpdate: fehlende `if operationId:` Guards bei Zeilen 101/125 verursachten "Operation None not found" Warnung wenn Agent-Tool webSearch ohne operationId aufrief
- 2026-05-11 | fix | gateway | SPEECH_TEAMS Prompt: spezifische Beispiele entfernt, Eskalationsregeln generisch gehalten
+- 2026-05-12 | fix | service-teams-browser-bot | Auth bot PiP loop fix: in full Teams web app, chat toggle navigates to Chat section → PiP → periodic scan reopens → PiP again (endless loop). Fix: added isAuthMode flag to ChatProcedure; in auth mode: skip chat panel toggle entirely, skip periodic reopen, skip panel-open preflight for sendChatMessage. Chat send uses direct input lookup in the meeting view. Replaced _returnToMeetingIfPip() approach (reactive) with prevention (don't toggle)
+- 2026-05-12 | fix | service-teams-browser-bot | Auth bot meeting minimized (PiP): chat button click hit Teams sidebar "Chats" navigation instead of in-meeting toggle → meeting minimized, all PeerConnections closed, video/audio broke. Fix: isDangerousNavButton filter excludes sidebar nav, tab-items, submenu triggers; aria-pressed fallback for panel detection in full Teams web app; _openMoreMenu scoped to calling toolbar
- 2026-05-11 | fix | service-teams-browser-bot | Anonymous bot stuck after lobby admission: _waitForMeetingAdmission now tracks lobby-to-meeting transition, waits patiently when lobby vanishes (= admitted), and reloads page as recovery; isInMeeting expanded with light-meetings + German selectors