fix(db): reset budget counters before validating on a fresh window (#9241)

Validated in local merge-train (devbox-vm-06-dev002) @ combined-tip (FAST gates green: static + changed tests + vitest — only pre-existing audit.test.ts flake). Evidence: /home/diegosouzapw/dev/proxys/OmniRoute/.claude/worktrees/merge-train-20260805-213228-suite.log
This commit is contained in:
Pedro Sakamoto
2026-08-05 21:45:20 -03:00
committed by GitHub
parent 3f9507f282
commit bc876740f5
3 changed files with 39 additions and 0 deletions

View File

@@ -0,0 +1 @@
- **fix(db):** `validateRegisteredKey` no longer rejects the first request of a fresh budget window when the previous window's usage already met the daily/hourly budget — the reset `UPDATE` zeroed the counters in the DB but the budget check still read the stale pre-reset snapshot, so the reset is now mirrored into the row before checking ([#9241](https://github.com/diegosouzapw/OmniRoute/pull/9241))

View File

@@ -384,6 +384,8 @@ export function validateRegisteredKey(rawKey: string): RegisteredKey | null {
const today = nowDay();
const hour = nowHour();
if (row.last_reset_day !== today || row.last_reset_hour !== hour) {
const dailyReset = row.last_reset_day !== today;
const hourlyReset = row.last_reset_hour !== hour;
db.prepare(
`
UPDATE registered_keys
@@ -393,6 +395,10 @@ export function validateRegisteredKey(rawKey: string): RegisteredKey | null {
WHERE id = ?
`
).run(today, hour, today, hour, row.id);
if (dailyReset) row.daily_used = 0;
if (hourlyReset) row.hourly_used = 0;
row.last_reset_day = today;
row.last_reset_hour = hour;
}
// Budget check

View File

@@ -213,6 +213,38 @@ test("validateRegisteredKey respects budget limits", async () => {
assert.equal(rk.validateRegisteredKey(created.rawKey), null);
});
test("validateRegisteredKey resets budget counters on a fresh window", async () => {
await resetStorage();
const issued = rk.issueRegisteredKey({
name: "Window Reset",
dailyBudget: 3,
});
assert.ok("rawKey" in issued);
if (!("rawKey" in issued)) return;
const db = core.getDbInstance();
const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000)
.toISOString()
.slice(0, 10);
const previousHour = new Date(Date.now() - 60 * 60 * 1000)
.toISOString()
.slice(0, 13);
rk.incrementRegisteredKeyUsage(issued.id);
rk.incrementRegisteredKeyUsage(issued.id);
rk.incrementRegisteredKeyUsage(issued.id);
db.prepare(
`UPDATE registered_keys SET daily_used = ?, hourly_used = ?, last_reset_day = ?, last_reset_hour = ? WHERE id = ?`,
).run(3, 3, yesterday, previousHour, issued.id);
// First validation of the new window must be accepted (not rejected against the
// stale pre-reset counters) and must return the freshly-reset counters.
const validated = rk.validateRegisteredKey(issued.rawKey);
assert.ok(validated !== null);
assert.equal(validated.dailyUsed, 0);
assert.equal(validated.hourlyUsed, 0);
});
// ──────────────── checkQuota ────────────────
test("checkQuota returns allowed true when no limits set", async () => {