fix: validate usage profile query type

This commit is contained in:
Kai (Tam Nhu) Tran
2026-05-30 15:20:15 -04:00
committed by Tam Nhu Tran
parent 62a4d44b58
commit 901bad2ec7
2 changed files with 25 additions and 8 deletions
+7 -2
View File
@@ -9,8 +9,13 @@ export interface ProfileScopedUsageData {
const PROFILE_NAME_REGEX = /^[A-Za-z0-9._-]+$/;
export function normalizeProfileQuery(profile?: string): string | undefined {
const value = profile?.trim();
export function normalizeProfileQuery(profile?: unknown): string | undefined {
if (profile === undefined) return undefined;
if (typeof profile !== 'string') {
throw new Error('Invalid profile filter');
}
const value = profile.trim();
if (!value || value === 'all') return undefined;
if (!PROFILE_NAME_REGEX.test(value)) {
throw new Error('Invalid profile filter');
@@ -83,11 +83,7 @@ function writeAssistantEntriesToDir(baseClaudeDir: string, entries: AssistantFix
},
});
fs.writeFileSync(
path.join(projectDir, `${entry.sessionId}.jsonl`),
`${line}\n`,
'utf-8'
);
fs.writeFileSync(path.join(projectDir, `${entry.sessionId}.jsonl`), `${line}\n`, 'utf-8');
}
}
@@ -222,7 +218,10 @@ describe('usage handlers semantics', () => {
res as never
);
const payload = res.payload as { success: boolean; data: Array<{ hour: string; requests: number }> };
const payload = res.payload as {
success: boolean;
data: Array<{ hour: string; requests: number }>;
};
const targetHour = payload.data.find((row) => row.hour === '2026-03-02 10:00');
expect(targetHour?.requests).toBe(3);
@@ -415,6 +414,19 @@ describe('usage handlers semantics', () => {
});
});
it('rejects non-string profile filters as validation errors', async () => {
for (const profile of [['work', 'default'], { name: 'work' }]) {
const res = createMockResponse();
await handlers.handleSummary({ query: { profile } } as never, res as never);
expect(res.statusCode).toBe(400);
expect(res.payload).toMatchObject({
success: false,
error: 'Invalid profile filter',
});
}
});
it('rejects reversed date ranges before computing summary totals', async () => {
const res = createMockResponse();