fd495ee61b
## Summary Fixes cross-user cache contamination for AI chat threads in multi-user workspaces. `agentChatThread` is the only user-scoped (`userWorkspaceId`-filtered) entry in `METADATA_NAME_TO_ENTITY_KEY`, but its create/update events were going through `WorkspaceEventBroadcaster`, which fans out to every active SSE stream in the workspace. Every client therefore received other users' threads into their local `agentChatThreads` metadata store (which is persisted to localStorage). On a subsequent session, `AgentChatThreadInitializationEffect` would pick the most-recently-updated thread — potentially another user's — and fire `GetChatMessages` against it; the server's `userWorkspaceId` filter didn't match, producing "Thread not found" errors (now 404 thanks to twentyhq/twenty#19831). ### The fix mirrors the RLS pattern already used for object records `ObjectRecordEventPublisher` already reads `streamData.authContext.userWorkspaceId` to filter per subscriber. Metadata events had no equivalent. This PR closes that gap with a minimal, opt-in change: - Add optional `recipientUserWorkspaceIds?: string[]` to `WorkspaceBroadcastEvent`. Omit → workspace-wide (unchanged for views, objects, fields, etc.). Set → delivered only to streams whose `authContext.userWorkspaceId` is in the list. - `WorkspaceEventBroadcaster.broadcast` builds the payload per stream and skips events whose recipient doesn't match. - Both `agentChatThread` broadcast call sites in `AgentChatService` now pass `recipientUserWorkspaceIds: [userWorkspaceId]`. ### Scope 3 files, +40/-11 LOC: - `subscriptions/workspace-event-broadcaster/types/workspace-broadcast-event.type.ts` - `subscriptions/workspace-event-broadcaster/workspace-event-broadcaster.service.ts` - `metadata-modules/ai/ai-chat/services/agent-chat.service.ts` ### Stale cache note Existing clients still carry poisoned localStorage from before this lands. They self-heal on sign-out/in because `clearAllSessionLocalStorageKeys` already drops `agentChatThreads`. If we want to actively flush on deploy, a frontend cache-version bump can follow in a separate PR. ### Related - twentyhq/twenty#19831 turns the resulting "Thread not found" from 500 to 404. This PR addresses the root cause; #19831 stops the Sentry noise. ## Test plan - [x] `npx nx typecheck twenty-server` - [x] `npx oxlint --type-aware` on all 3 files (0 warnings/errors) - [x] `npx prettier --check` on all 3 files - [ ] Manual: two users in the same workspace, user A creates/sends a chat thread — confirm user B's session does not receive the event and their `chatThreads` sidebar is unaffected - [ ] CI