LibreChat/api/server/services
Airam Hernández Hernández 277fdd2b43
🪪 feat: Optimized Entra ID Group Sync with Auto-Creation (#12606)
* feat: implement optimized Entra group sync with auto-creation

## Changes

### MUST FIX (Critical Issues) - RESOLVED

1. **BUG FIX: Prevent unintended user removal from existing groups**
   - ISSUE: db.syncUserEntraGroups() was called with only missing groups, causing removal
     from all existing Entra groups (full bidirectional sync behavior)
   - SOLUTION: Replaced with db.upsertGroupByExternalId() for each missing group followed
     by single bulkUpdateGroups() to add memberships (race-safe, idempotent)
   - BENEFIT: User memberships correctly maintained for mix of existing + new groups

2. **JSDoc @throws contradiction**
   - ISSUE: JSDoc declared function throws, but implementation catches all errors
   - SOLUTION: Removed @throws from JSDoc - function is best-effort
   - BENEFIT: Prevents unnecessary try/catch in caller code

3. **Missing test for group creation flow**
   - ISSUE: Auto-creating missing Entra groups had no test coverage
   - SOLUTION: Added regression test for mix of existing + new groups scenario
   - BENEFIT: Prevents future regressions on critical path

### SHOULD FIX (Important Improvements) - RESOLVED

4. **E11000 race condition handling**
   - SOLUTION: Upserts are idempotent and race-safe by design
   - BENEFIT: Concurrent logins no longer race each other

5. **Direct Mongoose access instead of db layer**
   - SOLUTION: Added findGroupsByExternalIds() helper to userGroup.ts
   - BENEFIT: Centralized data access, easier to add tenant scoping

6. **Serial DB round-trips on login path**
   - ISSUE: 40+ queries for user with 20 new groups
   - SOLUTION: Promise.all() for parallel upserts + single bulkUpdate
   - BENEFIT: ~10x performance improvement

7. **Graph API 429/503 throttling unhandled**
   - SOLUTION: Retry logic with exponential backoff (1s, 2s delays)
   - BENEFIT: Temporary API issues no longer cause permanent membership loss

8. **Sequential batch requests slow**
   - ISSUE: 200 groups = 10 batches × 200ms = ~2s sequential
   - SOLUTION: Promise.all() with concurrency limit (5 parallel batches)
   - BENEFIT: ~400ms total time

## Minor Fixes

- Removed dead code check
- PII removal: user._id instead of user.email in logs
- ES6 shorthand fixes
- Style consistency (blank lines)
- Projection optimization

## Verification

 npm run build - success
 npm run test:api - 61/61 passing (+ new regression test)
 npm run lint - no errors
 All feedback from danny-avila resolved

* docs: better JSDoc for the syncUserEntraGroupMemberships method

---------

Co-authored-by: Airam Hernández Hernández <airam.hernandez@intelequia.com>
2026-04-13 08:50:52 -04:00
..
__tests__ 🎯 fix: MCP Tool Misclassification from Action Delimiter Collision (#12512) 2026-04-01 22:36:21 -04:00
Artifacts 🪄 fix: Code Block handling in Artifact Updates (#11417) 2026-01-20 08:45:43 -05:00
Config 🏗️ refactor: Remove Redundant Caching, Migrate Config Services to TypeScript (#12466) 2026-03-30 16:49:48 -04:00
Endpoints ⚗️ feat: Agent Context Compaction/Summarization (#12287) 2026-03-21 14:28:56 -04:00
Files 🏗️ feat: bulkWrite isolation, pre-auth context, strict-mode fixes (#12445) 2026-03-28 16:43:50 -04:00
Runs 🧹 chore: Cleanup Logger and Utility Imports (#9935) 2025-10-01 23:30:47 -04:00
start 📦 refactor: Consolidate DB models, encapsulating Mongoose usage in data-schemas (#11830) 2026-03-21 14:28:53 -04:00
Threads 📦 refactor: Consolidate DB models, encapsulating Mongoose usage in data-schemas (#11830) 2026-03-21 14:28:53 -04:00
Tools 🏗️ feat: 3-Tier MCP Server Architecture with Config-Source Lazy Init (#12435) 2026-03-28 10:36:43 -04:00
ActionService.js 📦 refactor: Consolidate DB models, encapsulating Mongoose usage in data-schemas (#11830) 2026-03-21 14:28:53 -04:00
ActionService.spec.js ⚗️ feat: Agent Context Compaction/Summarization (#12287) 2026-03-21 14:28:56 -04:00
AssistantService.js 🪦 refactor: Remove Legacy Code (#10533) 2025-12-11 16:36:12 -05:00
AuthService.js 🏢 feat: Tenant-Scoped App Config in Auth Login Flows (#12434) 2026-03-27 16:08:43 -04:00
AuthService.spec.js 🏢 feat: Tenant-Scoped App Config in Auth Login Flows (#12434) 2026-03-27 16:08:43 -04:00
cleanup.js 📦 refactor: Consolidate DB models, encapsulating Mongoose usage in data-schemas (#11830) 2026-03-21 14:28:53 -04:00
createRunBody.js feat: Add Current Datetime to Assistants (v1/v2) (#4952) 2024-12-11 15:26:18 -05:00
GraphApiService.js 🪪 feat: Optimized Entra ID Group Sync with Auto-Creation (#12606) 2026-04-13 08:50:52 -04:00
GraphApiService.spec.js 🧵 refactor: Migrate Endpoint Initialization to TypeScript (#10794) 2025-12-11 16:37:16 -05:00
GraphTokenService.js 🔒 refactor: graphTokenController to use federated access token for OBO assertion (#11893) 2026-02-21 18:03:39 -05:00
initializeMCPs.js 🧵 feat: ALS Context Middleware, Tenant Threading, and Config Cache Invalidation (#12407) 2026-03-26 17:35:00 -04:00
initializeMCPs.spec.js v0.8.3-rc1 (#11856) 2026-02-18 20:36:03 -05:00
initializeOAuthReconnectManager.js 💫 feat: MCP OAuth Auto-Reconnect (#9646) 2025-09-17 16:49:36 -04:00
MCP.js ♻️ fix: Reuse Existing MCP OAuth Client Registrations to Prevent client_id Mismatch (#11925) 2026-04-03 22:15:08 -04:00
MCP.spec.js 🏗️ feat: 3-Tier MCP Server Architecture with Config-Source Lazy Init (#12435) 2026-03-28 10:36:43 -04:00
PermissionService.js 🪪 feat: Optimized Entra ID Group Sync with Auto-Creation (#12606) 2026-04-13 08:50:52 -04:00
PermissionService.spec.js 🪪 feat: Optimized Entra ID Group Sync with Auto-Creation (#12606) 2026-04-13 08:50:52 -04:00
PluginService.js 🔌 feat: MCP Reinitialization and OAuth in UI (#8598) 2025-07-22 22:52:45 -04:00
systemGrant.spec.js 📜 feat: Implement System Grants for Capability-Based Authorization (#11896) 2026-03-21 14:28:54 -04:00
ToolService.js 🎯 fix: MCP Tool Misclassification from Action Delimiter Collision (#12512) 2026-04-01 22:36:21 -04:00
twoFactorService.js 🔑 fix: Require OTP Verification for 2FA Re-Enrollment and Backup Code Regeneration (#12223) 2026-03-14 01:51:31 -04:00