mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-11-12 17:56:50 +00:00
* 🔎 fix: Keep Scoped Package Frames Out of the Log Email Redactor The log redactor read node_modules/@scope/pkg/... as an address and replaced whole stack frame locations with [REDACTED_EMAIL], in file, console and OpenTelemetry output alike. An @ between path separators now names a scoped package; addresses beside such frames are still masked. * 🪪 feat: Name the Build and Loaded Config on OpenTelemetry Records service.version now defaults to the image's BUILD_COMMIT ahead of the npm package version. Each successful librechat.yaml load records a short digest of the parsed file, which exported log records and request spans carry as librechat.config.digest, and applies telemetry.stackTraceLimit to Error.stackTraceLimit; unset keeps the process default. * fix: Publish telemetry settings with the accepted base config * fix: Initialize process settings before adopting cached config * fix: Preserve runtime settings when cache writes are refused * fix: Keep telemetry identity local and propagate Redis write errors * fix: Partition merged config caches by the local base * fix: Keep config cache failures recoverable * test: Verify cache recovery contracts with typed fixtures --------- Co-authored-by: Lia <lia@librechat.ai>
43 lines
1.5 KiB
JavaScript
43 lines
1.5 KiB
JavaScript
jest.mock('@librechat/api', () => {
|
|
const api = jest.requireActual('@librechat/api');
|
|
return { ...api, standardCache: jest.fn(api.standardCache) };
|
|
});
|
|
|
|
const { standardCache } = require('@librechat/api');
|
|
const { logger } = require('@librechat/data-schemas');
|
|
const { CacheKeys } = require('librechat-data-provider');
|
|
const getLogStores = require('./getLogStores');
|
|
const appConfigCacheArgs = standardCache.mock.calls.find(([key]) => key === CacheKeys.APP_CONFIG);
|
|
|
|
describe('auditCache', () => {
|
|
it('requires APP_CONFIG publication errors to propagate', () => {
|
|
expect(appConfigCacheArgs).toEqual([
|
|
CacheKeys.APP_CONFIG,
|
|
undefined,
|
|
undefined,
|
|
{ throwOnErrors: true },
|
|
]);
|
|
});
|
|
|
|
it('logs counts and TTL info without cache keys or values', async () => {
|
|
const secretKey = 'user-id-1234567890';
|
|
const secretValue = 'super-secret-access-token';
|
|
const store = getLogStores(CacheKeys.ADMIN_OAUTH_EXCHANGE);
|
|
await store.set(secretKey, { access_token: secretValue });
|
|
|
|
const info = jest.spyOn(logger, 'info').mockImplementation(() => {});
|
|
const log = jest.spyOn(console, 'log').mockImplementation(() => {});
|
|
getLogStores.auditCache();
|
|
|
|
const output = JSON.stringify(info.mock.calls);
|
|
expect(output).toContain(CacheKeys.ADMIN_OAUTH_EXCHANGE);
|
|
expect(output).toContain('count=1');
|
|
expect(output).not.toContain(secretValue);
|
|
expect(output).not.toContain(secretKey);
|
|
expect(log).not.toHaveBeenCalled();
|
|
|
|
info.mockRestore();
|
|
log.mockRestore();
|
|
await store.clear();
|
|
});
|
|
});
|