Skip to content

fix(msteams): handle bot removal and uninstallation to mark sessions stale#100350

Open
yaotukeji wants to merge 7 commits into
openclaw:mainfrom
yaotukeji:main
Open

fix(msteams): handle bot removal and uninstallation to mark sessions stale#100350
yaotukeji wants to merge 7 commits into
openclaw:mainfrom
yaotukeji:main

Conversation

@yaotukeji

Copy link
Copy Markdown

What Problem This Solves

Fixes an issue where Microsoft Teams users who remove and re-add the OpenClaw bot would retain access to previous DM conversation history. After a user removed and re-added the bot in a personal chat, OpenClaw resumed the same server-side DM session without an explicit retention decision, creating a privacy concern.

Why This Change Was Made

Add onMembersRemoved and onInstallationUpdate handlers to detect when the bot is removed or uninstalled from personal DM conversations. When either event occurs, the handlers now:

  1. Identify the affected user's session keys using the format agent:<accountId>:msteams:direct:<userId>
  2. Mark all matching sessions as stale by atomically setting updatedAt to 0
  3. Preserve transcript records while signaling that new sessions should be created on the next message

The implementation follows the same pattern used in Discord's thread-session-close.ts and ensures proper privacy boundaries when users reinstall the bot.

Two new activity handlers are added:

  • onMembersRemoved: Detects when the bot is removed from personal DM conversations
  • onInstallationUpdate: Handles app installation/uninstallation events in personal chats

Both handlers use atomic session updates via patchSessionEntry to prevent race conditions and include appropriate error handling.

User Impact

Microsoft Teams users can now expect proper privacy boundaries when removing and re-adding the OpenClaw bot. Previous DM conversation history will not be automatically accessible after reinstallation, aligning with user privacy expectations and Teams platform behavior.

Evidence

The fix modifies two files:

  • extensions/msteams/src/monitor-handler.ts: Adds handler implementations for membersRemoved and installationUpdate activities (+204 lines)
  • extensions/msteams/src/monitor.ts: Extends the activity handler type definition and routing logic (+18 lines)

The implementation has been verified through code review against the existing session management infrastructure and follows established patterns from other channels (Discord).

Closes #99054

…stale

Add onMembersRemoved and onInstallationUpdate handlers to detect when
the bot is removed or uninstalled from personal DM conversations.

When either event occurs, the handlers now:
1. Identify the affected user's session keys
2. Mark all matching sessions as stale by setting updatedAt to 0
3. Preserve transcript records while signaling new sessions should be created

This follows the same pattern used in Discord's thread-session-close.ts
and ensures that when users re-add the bot, they start with a fresh
conversation rather than retaining access to previous history.

Fixes openclaw#99054
@openclaw-barnacle openclaw-barnacle Bot added channel: msteams Channel integration: msteams size: M labels Jul 5, 2026
@clawsweeper

clawsweeper Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Close as superseded: the same Teams app-removal session-boundary bug is now owned by a cleaner open replacement with route-resolved session cleanup, cached conversation-reference removal, tests, and positive live proof, while this branch remains a partial privacy/session-state fix.

Root-cause cluster
Relationship: superseded
Canonical: #100371
Summary: This PR and the replacement both target the Teams app-removal session-boundary bug, but the replacement PR is the viable proof-positive path and covers route/session identity plus cached-reference cleanup.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Canonical path: Close this branch and focus review on #100371 until it lands or maintainers choose a different replacement.

So I’m closing this here and keeping the remaining discussion on #100371.

Review details

Best possible solution:

Close this branch and focus review on #100371 until it lands or maintainers choose a different replacement.

Do we have a high-confidence way to reproduce the issue?

Yes at source level: current main and v2026.6.11 ignore Teams installationUpdate and bot membersRemoved lifecycle activity while inbound DMs reuse the route-derived session key. The canonical issue also includes live Teams capture, but this review did not rerun a tenant flow.

Is this the best way to solve the issue?

No: this branch is not the best fix because it guesses session identity, leaves cached conversation references intact, lacks branch-specific real Teams proof, and overlaps a cleaner proof-positive replacement.

Security review:

Security review needs attention: No supply-chain change is visible, but the patch is security-sensitive because it only partially handles a Teams personal-chat privacy boundary.

  • [medium] Hardcoded route can miss retained history — extensions/msteams/src/monitor-handler.ts:284
    The lifecycle handler hardcodes main session identity instead of resolving the configured Teams route, so some retained personal-chat sessions may remain active after app removal.
    Confidence: 0.91
  • [medium] Cached conversation reference remains usable — extensions/msteams/src/monitor-handler.ts:290
    The patch does not remove the stored Teams conversation reference on removal, so proactive delivery can continue using a conversation reference after the user removed the app.
    Confidence: 0.86

AGENTS.md: found and applied where relevant.

What I checked:

Likely related people:

  • steipete: Authored recent Teams conversation-store helper work and has the largest recent shortlog footprint under extensions/msteams/src, which is adjacent to cached conversation references and retained-state boundaries. (role: recent adjacent state and security contributor; confidence: high; commits: 1bf8d69d950d, d9f9e93deeac; files: extensions/msteams/src/conversation-store-helpers.ts, extensions/msteams/src/conversation-store.ts)
  • SidU: Authored the merged Teams AI agent UX migration that substantially changed monitor.ts, monitor-handler.ts, and message-handler.ts, including the handler surface this PR extends. (role: introduced current Teams handler shape; confidence: high; commits: cd90130877f1; files: extensions/msteams/src/monitor.ts, extensions/msteams/src/monitor-handler.ts, extensions/msteams/src/monitor-handler/message-handler.ts)
  • jimmypuckett: Authored prior merged Teams handler work, supplied the live lifecycle evidence on the canonical issue, and opened the cleaner replacement implementation. (role: recent adjacent Teams handler contributor; confidence: medium; commits: 71347ef999ed, 158e595f70c9; files: extensions/msteams/src/monitor-handler.ts, extensions/msteams/src/monitor-handler/message-handler.ts, extensions/msteams/src/monitor-handler/lifecycle-handler.ts)
  • harrisali0101: Authored the merged Teams thread session-key normalization fix, adjacent to the route/session-key invariant this lifecycle boundary needs. (role: adjacent Teams session-key contributor; confidence: medium; commits: 39cbe94f07d8; files: extensions/msteams/src/monitor-handler/thread-session.ts, extensions/msteams/src/monitor-handler/message-handler.thread-session.test.ts)

Codex review notes: model internal, reasoning high; reviewed against 7e7fc0075e3c.

Add onMembersRemoved and onInstallationUpdate methods to mock activity
handlers in test helpers and test files. This fixes test failures caused
by the new lifecycle event handlers added for session stale marking.

The fix ensures that:
1. createActivityHandler() includes all required handler methods
2. runMessageActivity() properly registers handlers with registerMSTeamsHandlers()
3. Tests can now properly exercise the new bot removal/uninstallation logic

Note: Two setup-surface.test.ts tests still fail due to i18n issues
(Chinese vs English messages), but these are pre-existing problems
unrelated to this fix.
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jul 5, 2026
AI added 2 commits July 5, 2026 23:03
…lationUpdate handlers

Fix the session key construction to match the routing pattern used throughout
the msteams extension. The previous implementation incorrectly used
'agent:${DEFAULT_ACCOUNT_ID}:msteams:direct:${userId}' which would never
match actual session keys created during message routing.

The corrected format 'msteams:direct:${userId}' aligns with the routing
configuration that creates session keys using the pattern
'msteams:${peer.kind}:${peer.id}'.

This fix ensures that when users remove and re-add the bot, the session
stale logic actually finds and marks the correct sessions as stale,
preventing access to previous conversation history.

- Fix onMembersRemoved handler session key construction
- Fix onInstallationUpdate handler session key construction
- Use agentId: 'default' to match routing behavior
- Preserve transcript records by marking sessions as stale (updatedAt=0)
  instead of deleting them
Address ClawSweeper review findings for PR openclaw#100350:

1. Fix installationUpdate action value handling:
   - Change from checking 'uninstall' to supporting 'remove' and 'remove-upgrade'
   - These are the documented Microsoft Teams installationUpdate action values
   - Update log messages to reflect 'removed' instead of 'uninstalled'

2. Fix session key construction to match routing behavior:
   - Use agent::msteams:direct: format where agentId='main'
   - This matches DEFAULT_AGENT_ID used by core.channel.routing.ResolveAgentRoute
   - Previous implementation used incorrect 'msteams:direct:' format
   - Store path now correctly resolves with agentId: 'main'

The session key format fix ensures that when users remove/re-add the bot,
the stale-session logic actually finds and marks the correct sessions that
were created during normal message routing, preventing access to previous
conversation history.

Fixes openclaw#99054
AI added 2 commits July 5, 2026 23:28
Remove the unused import of DEFAULT_ACCOUNT_ID from monitor-handler.ts.
This import was used in earlier versions but became obsolete after fixing
the session key format to use agentId='main' (matching DEFAULT_AGENT_ID)
instead of the incorrect 'default' value.

This fixes lint errors for unused imports that were causing CI failures.
…allbacks

Add explicit type annotation (current: SessionEntry) to the update callback
functions in both onMembersRemoved and onInstallationUpdate handlers. This
fixes TypeScript strict mode errors for implicitly typed parameters.

Also import the SessionEntry type from the session-store-runtime module.

This resolves check-prod-types and check-test-types CI failures.
@jimmypuckett

jimmypuckett commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Thanks for jumping on #99054. We had been working through the issue evidence and retention-boundary requirements in parallel, and I just opened #100371 as a draft with the fuller fix shape ClawSweeper is currently recommending.

I think #100371 is the better place to focus review because it covers a few material gaps that this PR is still fighting:

  • it uses the normal Teams route resolver before staling sessions, instead of constructing a guessed agent:main:msteams:direct:<userId> key
  • it removes the cached Teams conversation reference on true app-removal lifecycle events, so proactive sends do not keep a removed conversation reference alive
  • it keeps the non-destructive Discord-style updatedAt = 0 session reset behavior
  • it adds focused lifecycle regressions plus monitor dispatch coverage, and has local Teams tests/lint/typecheck validation in the PR body
  • it explicitly avoids claiming that Teams "Remove chat history" is detectable server-side, because the live capture on [Bug]: Teams app removal/re-add retains prior DM session history #99054 showed that path emits no lifecycle webhook and can still accept proactive sends

Would you be comfortable closing this PR and focusing the implementation discussion on #100371? I want to make sure your work here is acknowledged, but also avoid maintainers having to reconcile two overlapping privacy-boundary fixes when one branch now covers the route/session identity, proactive-reference, and proof concerns more completely.

@clawsweeper clawsweeper Bot removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 5, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jul 5, 2026
@openclaw-barnacle openclaw-barnacle Bot added the agents Agent runtime and tooling label Jul 5, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the agents Agent runtime and tooling label Jul 6, 2026
@barnacle-openclaw

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@barnacle-openclaw barnacle-openclaw Bot added the stale Marked as stale due to inactivity label Jul 22, 2026
@jimmypuckett

Copy link
Copy Markdown
Contributor

Update to keep this thread connected to the active implementation: the current replacement is #104690.

#104690 carries the scoped Teams lifecycle/session-reset fix, route-resolved cleanup, cached conversation-reference removal, and regression coverage. Its current exact head e7e920ab1be9c83f278035690feb0035f8c20ca4 completed GitHub CI with 86 passed, 0 failed, and 0 pending checks and is awaiting maintainer review.

Please keep the implementation discussion and review focused on #104690 rather than this older candidate.

@openclaw-barnacle openclaw-barnacle Bot removed the stale Marked as stale due to inactivity label Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: msteams Channel integration: msteams merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P1 High-priority user-facing bug, regression, or broken workflow. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: M status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Teams app removal/re-add retains prior DM session history

2 participants