diff --git a/packages/web/server/lib/quota/providers/opencode-go.js b/packages/web/server/lib/quota/providers/opencode-go.js index b6b97370..f87710a7 100644 --- a/packages/web/server/lib/quota/providers/opencode-go.js +++ b/packages/web/server/lib/quota/providers/opencode-go.js @@ -25,7 +25,7 @@ export const parseOpenCodeGoUsage = (payload) => { if (typeof resetAt !== 'string' || !Number.isFinite(new Date(resetAt).getTime())) continue; windows[key] = toUsageWindow({ usedPercent: Math.min(100, Math.max(0, usedPercent)), - resetAt, + resetAt: new Date(resetAt).getTime(), windowSeconds: null, }); } diff --git a/packages/web/server/lib/quota/providers/opencode-go.test.js b/packages/web/server/lib/quota/providers/opencode-go.test.js index 505cbee5..f0a89a9b 100644 --- a/packages/web/server/lib/quota/providers/opencode-go.test.js +++ b/packages/web/server/lib/quota/providers/opencode-go.test.js @@ -27,11 +27,36 @@ describe('OpenCode Go quota provider', () => { it('parses partial API usage windows', () => { const windows = parseOpenCodeGoUsage({ usage: { rolling: { percent: 25, resetsAt: '2026-08-12T12:00:00.000Z' }, weekly: { percent: 40, resetsAt: '2026-08-19T12:00:00.000Z' } } }); expect(windows['5h'].usedPercent).toBe(25); - expect(windows['5h'].resetAt).toBe('2026-08-12T12:00:00.000Z'); + expect(windows['5h'].resetAt).toBe(Date.parse('2026-08-12T12:00:00.000Z')); expect(windows.weekly.usedPercent).toBe(40); expect(windows.monthly).toBeUndefined(); }); + it('returns numeric reset timestamps for all usage windows', async () => { + const resetsAt = '2026-10-01T00:00:00.000Z'; + const windows = await fetchOpenCodeGoUsage('test-key', async () => new Response(JSON.stringify({ + usage: { + rolling: { percent: 25, resetsAt }, + weekly: { percent: 40, resetsAt }, + monthly: { percent: 60, resetsAt }, + }, + }))); + expect(Object.keys(windows)).toEqual(['5h', 'weekly', 'monthly']); + for (const window of Object.values(windows)) { + expect(window.resetAt).toBe(Date.parse(resetsAt)); + } + }); + + it('preserves valid windows when another reset date is invalid', () => { + const windows = parseOpenCodeGoUsage({ usage: { + rolling: { percent: 25, resetsAt: 'invalid' }, + weekly: { percent: 40, resetsAt: '2026-08-19T12:00:00.000Z' }, + monthly: { percent: 60, resetsAt: null }, + } }); + expect(Object.keys(windows)).toEqual(['weekly']); + expect(windows.weekly.resetAt).toBe(Date.parse('2026-08-19T12:00:00.000Z')); + }); + it('does not expose credentials in authentication errors', async () => { await expect(fetchOpenCodeGoUsage('secret', async () => new Response('', { status: 403 }))).rejects.toThrow('authentication failed'); });