mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-03-12 11:02:37 +01:00
* chore: imports
* chore: optional chaining in `spendTokens.spec.ts`
* feat: Add tenantId field to all MongoDB schemas for multi-tenant isolation
- Add AsyncLocalStorage-based tenant context (`tenantContext.ts`) for
request-scoped tenantId propagation without modifying method signatures
- Add Mongoose `applyTenantIsolation` plugin that injects `{ tenantId }`
into all query filters when tenant context is present, with
`TENANT_ISOLATION_STRICT` env var for fail-closed production mode
- Add optional `tenantId` field to all 28 collection schemas
- Update all compound unique indexes to include tenantId (email, OAuth IDs,
role names, serverName, conversationId+user, messageId+user, etc.)
- Apply tenant isolation plugin in all 28 model factories
- Add `tenantId?: string` to all TypeScript document interfaces
Behaviorally inert — transitional mode (default) passes through all queries
unchanged. No migration required for existing deployments.
* refactor: Update tenant context and enhance tenant isolation plugin
- Changed `tenantId` in `TenantContext` to be optional, allowing for more flexible usage.
- Refactored `runAsSystem` function to accept synchronous functions, improving usability.
- Introduced comprehensive tests for the `applyTenantIsolation` plugin, ensuring correct tenant filtering in various query scenarios.
- Enhanced the plugin to handle aggregate queries and save operations with tenant context, improving data isolation capabilities.
* docs: tenant context documentation and improve tenant isolation tests
- Added detailed documentation for the `tenantStorage` AsyncLocalStorage instance in `tenantContext.ts`, clarifying its usage for async tenant context propagation.
- Updated tests in `tenantIsolation.spec.ts` to improve clarity and coverage, including new tests for strict mode behavior and tenant context propagation through await boundaries.
- Refactored existing test cases for better readability and consistency, ensuring robust validation of tenant isolation functionality.
* feat: Enhance tenant isolation by preventing tenantId mutations in update operations
- Added a new function to assert that tenantId cannot be modified through update operators in Mongoose queries.
- Implemented middleware to enforce this restriction during findOneAndUpdate, updateOne, and updateMany operations.
- Updated documentation to reflect the new behavior regarding tenantId modifications, ensuring clarity on tenant isolation rules.
* feat: Enhance tenant isolation tests and enforce tenantId restrictions
- Updated existing tests to clarify behavior regarding tenantId preservation during save and insertMany operations.
- Introduced new tests to validate that tenantId cannot be modified through update operations, ensuring strict adherence to tenant isolation rules.
- Added checks for mismatched tenantId scenarios, reinforcing the integrity of tenant context propagation.
- Enhanced test coverage for async context propagation and mutation guards, improving overall robustness of tenant isolation functionality.
* fix: Remove duplicate re-exports in utils/index.ts
Merge artifact caused `string` and `tempChatRetention` to be exported
twice, which produces TypeScript compile errors for duplicate bindings.
* fix: Resolve admin capability gap in multi-tenant mode (TODO #12091)
- hasCapabilityForPrincipals now queries both tenant-scoped AND
platform-level grants when tenantId is set, so seeded ADMIN grants
remain effective in tenant mode.
- Add applyTenantIsolation to SystemGrant model factory.
* fix: Harden tenant isolation plugin
- Add replaceGuard for replaceOne/findOneAndReplace to prevent
cross-tenant document reassignment via replacement documents.
- Cache isStrict() result to avoid process.env reads on every query.
Export _resetStrictCache() for test teardown.
- Replace console.warn with project logger (winston).
- Add 5 new tests for replace guard behavior (46 total).
* style: Fix import ordering in convo.ts and message.ts
Move type imports after value imports per project style guide.
* fix: Remove tenant isolation from SystemGrant, stamp tenantId in replaceGuard
- SystemGrant is a cross-tenant control plane whose methods handle
tenantId conditions explicitly. Applying the isolation plugin
injects a hard equality filter that overrides the $and/$or logic
in hasCapabilityForPrincipals, making platform-level ADMIN grants
invisible in tenant mode.
- replaceGuard now stamps tenantId into replacement documents when
absent, preventing replaceOne from silently stripping tenant
context. Replacements with a matching tenantId are allowed;
mismatched tenantId still throws.
* test: Add multi-tenant unique constraint and replace stamping tests
- Verify same name/email can exist in different tenants (compound
unique index allows it).
- Verify duplicate within same tenant is rejected (E11000).
- Verify tenant-scoped query returns only the correct document.
- Update replaceOne test to assert tenantId is stamped into
replacement document.
- Add test for replacement with matching tenantId.
* style: Reorder imports in message.ts to align with project style guide
* feat: Add migration to drop superseded unique indexes for multi-tenancy
Existing deployments have single-field unique indexes (e.g. { email: 1 })
that block multi-tenant operation — same email in different tenants
triggers E11000. Mongoose autoIndex creates the new compound indexes
but never drops the old ones.
dropSupersededTenantIndexes() drops all 19 superseded indexes across 11
collections. It is idempotent, skips missing indexes/collections, and
is a no-op on fresh databases.
Must be called before enabling multi-tenant middleware on an existing
deployment. Single-tenant deployments are unaffected (old indexes
coexist harmlessly until migration runs).
Includes 11 tests covering:
- Full upgrade simulation (create old indexes, drop them, verify gone)
- Multi-tenant writes work after migration (same email, different tenant)
- Intra-tenant uniqueness preserved (duplicate within tenant rejected)
- Fresh database (no-op, no errors)
- Partial migration (some collections exist, some don't)
- SUPERSEDED_INDEXES coverage validation
* fix: Update systemGrant test — platform grants now satisfy tenant queries
The TODO #12091 fix intentionally changed hasCapabilityForPrincipals to
match both tenant-scoped AND platform-level grants. The test expected
the old behavior (platform grant invisible to tenant query). Updated
test name and expectation to match the new semantics.
* fix: Align getCapabilitiesForPrincipal with hasCapabilityForPrincipals tenant query
getCapabilitiesForPrincipal used a hard tenantId equality filter while
hasCapabilityForPrincipals uses $and/$or to match both tenant-scoped
and platform-level grants. This caused the two functions to disagree
on what grants a principal holds in tenant mode.
Apply the same $or pattern: when tenantId is provided, match both
{ tenantId } and { tenantId: { $exists: false } }.
Adds test verifying platform-level ADMIN grants appear in
getCapabilitiesForPrincipal when called with a tenantId.
* fix: Remove categories from tenant index migration
categoriesSchema is exported but never used to create a Mongoose model.
No Category model factory exists, no code constructs a model from it,
and no categories collection exists in production databases. Including
it in the migration would attempt to drop indexes from a non-existent
collection (harmlessly skipped) but implies the collection is managed.
* fix: Restrict runAsSystem to async callbacks only
Sync callbacks returning Mongoose thenables silently lose ALS context —
the system bypass does nothing and strict mode throws with no indication
runAsSystem was involved. Narrowing to () => Promise<T> makes the wrong
pattern a compile error. All existing call sites already use async.
* fix: Use next(err) consistently in insertMany pre-hook
The hook accepted a next callback but used throw for errors. Standardize
on next(err) for all error paths so the hook speaks one language —
callback-style throughout.
* fix: Replace optional chaining with explicit null assertions in spendTokens tests
Optional chaining on test assertions masks failures with unintelligible
error messages. Add expect(result).not.toBeNull() before accessing
properties, so a null result produces a clear diagnosis instead of
"received value must be a number".
|
||
|---|---|---|
| .. | ||
| api | ||
| client | ||
| data-provider | ||
| data-schemas | ||