You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: close the gaps a red-team pass found in spend exclusions
Four of these are real defects, two of them regressions from the two
commits above.
Quota sweep no longer cancels excluded trials. `_active_trial_predicates`
lost the key-exclusion filter when that feature was deleted and gained
nothing in its place, so `cancel_trials_if_quota_reached` would kill every
active trial in an excluded experiment — trials that contributed nothing
to the number that tripped the cap and reserve nothing against it, so
killing them frees no headroom. Adds both filters and a test, since the
test that used to cover this was rewritten around the deleted feature.
Model exclusions no longer silently no-op. `trials.model` is written by
the agent-aware `normalize_trial_model`, which re-routes ids — `kimi-k2`
is stored as `moonshot/kimi-k2`, Claude models as Bedrock ids — so storing
what the operator typed registered a row that matched nothing, with no
feedback. The endpoint now resolves the typed spelling against the values
trials actually store, registers every match (one model can have two
stored spellings, and excluding one would leave half the spend counting),
and 404s when nothing matches. The SQL predicate and its Python twin now
both compare `trials.model` verbatim, so they can no longer disagree about
which rows are excluded.
The CLI could never write. Mutations gated on `can_manage_api_keys`, which
rejects API-key auth by design because it guards key management itself —
so every `oddish cost-exclusions add` was a guaranteed 403 telling the
operator to use the credential they were already using. Operator-org
membership is the gate; `require_admin` already counts a full-scope key as
admin.
The experiment Cost tile claimed gathered spend was comped. It covers
member trials including gathered ones, but was passed the whole-experiment
excluded flag, which by design only excludes homed trials. Excluding a
collection is now rejected outright for the same reason: it homes no
trials, so it would exclude nothing while claiming everything was free.
Also: migration resets `SET LOCAL lock_timeout` (all pending revisions
share one transaction, so it leaked into later ones) and touches `trials`
last on downgrade as it already did on upgrade; restores the `llm_key_hash`
entry in Carl's SQL deny-list, which is inert once the column is gone but
is the only guard where code runs ahead of schema; CLI emits JSON on every
error branch and resolves non-canonical model spellings on remove.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zmdrcCqnkVM6hWjhPu2T9
0 commit comments