From c43df0ec03f98504e710e520b4d20d9554e1d0f2 Mon Sep 17 00:00:00 2001 From: Nalla Prakash <81852531+prakashNalla@users.noreply.github.com> Date: Thu, 29 Oct 2026 21:46:15 +0530 Subject: [PATCH] fix(server): reject a retention.conversationsDays that isn't above 0 --- .changeset/retention-days-check.md | 5 +++++ packages/server/src/handler.ts | 4 ++++ packages/server/tests/storage-config.test.ts | 6 ++++++ 3 files changed, 15 insertions(+) create mode 100644 .changeset/retention-days-check.md diff --git a/.changeset/retention-days-check.md b/.changeset/retention-days-check.md new file mode 100644 index 00000000..bd87e1f0 --- /dev/null +++ b/.changeset/retention-days-check.md @@ -0,0 +1,5 @@ +--- +"@chatcops/server": patch +--- + +`createChatHandler` now throws when `retention.conversationsDays` is 0, negative or not a finite number. Before, 0 or a negative value made `purge()` delete every conversation. diff --git a/packages/server/src/handler.ts b/packages/server/src/handler.ts index b5d56a8d..64ab8437 100644 --- a/packages/server/src/handler.ts +++ b/packages/server/src/handler.ts @@ -81,6 +81,10 @@ export function createChatHandler(config: ChatCopsServerConfig) { } const rateLimit = { maxRequests: 30, windowMs: 60_000, ...config.rateLimit }; if (rateLimit.maxRequests <= 0) throw new Error('maxRequests must be greater than 0'); + const retentionDays = config.retention?.conversationsDays; + if (retentionDays !== undefined && (!Number.isFinite(retentionDays) || retentionDays <= 0)) { + throw new Error('retention.conversationsDays must be a number greater than 0'); + } const rateLimiter = createRateLimiter(counters, { limit: rateLimit.maxRequests, windowMs: rateLimit.windowMs, diff --git a/packages/server/tests/storage-config.test.ts b/packages/server/tests/storage-config.test.ts index e6399f10..64e48a80 100644 --- a/packages/server/tests/storage-config.test.ts +++ b/packages/server/tests/storage-config.test.ts @@ -77,6 +77,12 @@ describe('purge', () => { cleanup(); }); + it.each([0, -1, Number.NaN, Number.POSITIVE_INFINITY])('throws when conversationsDays is %s', (days) => { + expect(() => createChatHandler({ provider: scriptedProvider([]), systemPrompt: 'x', retention: { conversationsDays: days } })).toThrow( + 'retention.conversationsDays must be a number greater than 0' + ); + }); + it('resolves null when the store has no purge', async () => { const conversationStore = { get: async () => null, save: async () => {}, delete: async () => {} }; const { purge, cleanup } = createChatHandler({ provider: scriptedProvider([]), systemPrompt: 'x', conversationStore });