Skip to content

check_quota / record_usage time-of-check / time-of-use race — concurrent calls pass quota then each charge #3736

Description

@houko

Location

  • crates/librefang-kernel/src/scheduler.rs:140-216
  • crates/librefang-kernel/src/kernel/mod.rs:4737-4780

Problem
check_quota (line 4737) reads tracker, compares to limit, returns OK. The LLM call then takes seconds. record_usage (line 4780) increments the tracker after success. With N concurrent agent sessions (or trigger fires) that all enter send_message_full between check and record, all N pass the check (tracker still at pre-check value), all N spend tokens, then all N record — total spend can be Nx the burst cap.

Impact
Hourly token budget is a soft suggestion under concurrency. burst_cap = token_limit / 5 rate fence is bypassable similarly. Final billing is correct but the preventive circuit-breaker doesn't fire.

Fix
Add a reserve(estimated_max_tokens) step that atomically charges a conservative upper bound at check-time, then record_usage reconciles with the real number (refunding unused). Or merge the two into a pre_charge + settle API.


Filed via automated multi-perspective audit (security / concurrency / architecture / error-handling / frontend / performance subagents). Curated against #3359#3409 to avoid duplicates.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/kernelCore kernel (scheduling, RBAC, workflows)bugSomething isn't workingneeds-triageAuto-applied when the issue title/body matched no area label — needs maintainer reviewseverity/highSignificant functional, security, or performance impact

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions