mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-06 07:12:12 +03:00
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:
1
changelog.d/fixes/9241-registered-keys-window-reset.md
Normal file
1
changelog.d/fixes/9241-registered-keys-window-reset.md
Normal 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))
|
||||
@@ -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
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
Reference in New Issue
Block a user