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.
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_usagestream (independent ofTPK_CHAT_AUDIT),daily_token_limiton 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:
daily_question_limitcolumn onkg_roles(and no per-user override to matchdaily_token_limit).chat_usagecurrently has onlyts, username, tokens— the issue's proposedquestionscolumn was dropped (src/tpk/db.py:223). A question cap needs a per-turn question count (either aquestionscolumn here, orcount()of turns in the window).POST /chatand no editor field.Scope if built
daily_question_limit(role + optional per-user override), migrated via_add_column_if_missing; 0/unset = unlimited; admin exempt — mirror thedaily_token_limitplumbing exactly.count >= daily_question_limit, combined with the token check so whichever trips first blocks.Low priority: the token budget already controls real cost; this is a convenience guardrail.