Skip to content

Optional daily question cap for non-admin users (secondary guardrail to the #62 token budget) #68

Description

@gangtao

Follow-up to #62 (split out so #62 can close with the token budget delivered in #63).

What's already in place

The per-user daily token budget shipped in #63: metering to the append-only chat_usage stream (independent of TPK_CHAT_AUDIT), daily_token_limit on roles + per-user override + global default, POST /chat → 429 with reset time, admin exempt, editor UI + friendly 429. The token budget is the primary cost control and covers the main risk.

What's missing — the optional secondary question cap

#62 also proposed an optional daily question cap as an easy-to-explain secondary guardrail ("a role can set either, both, or neither"; whichever limit is hit first blocks until reset). None of it was built:

  • No daily_question_limit column on kg_roles (and no per-user override to match daily_token_limit).
  • chat_usage currently has only ts, username, tokens — the issue's proposed questions column was dropped (src/tpk/db.py:223). A question cap needs a per-turn question count (either a questions column here, or count() of turns in the window).
  • No enforcement in POST /chat and no editor field.

Scope if built

  • Add daily_question_limit (role + optional per-user override), migrated via _add_column_if_missing; 0/unset = unlimited; admin exempt — mirror the daily_token_limit plumbing exactly.
  • Count today's questions for the user (UTC-day window, same as the token window) and 429 when count >= daily_question_limit, combined with the token check so whichever trips first blocks.
  • Editor numeric field alongside the token limit; reuse the same friendly 429 UI.
  • Tests: question metering/counting, over/under enforcement, admin bypass, reset-window boundary, and token+question interaction (first-to-trip wins).

Low priority: the token budget already controls real cost; this is a convenience guardrail.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions