Skip to content

fix(proxy): bypass engages through installation excluded_models - #797

Merged
steventohme merged 6 commits into
mainfrom
fix/bypass-ignore-installation-excluded-models
Jul 20, 2026
Merged

fix(proxy): bypass engages through installation excluded_models#797
steventohme merged 6 commits into
mainfrom
fix/bypass-ignore-installation-excluded-models

Conversation

@steventohme

Copy link
Copy Markdown
Collaborator

Problem

The subscription usage-bypass gate (the "strict pass-through until low" feature) refused to engage whenever the requested model was on the installation excluded_models list. An org that opted into bypass but also had a stale/broad excluded_models policy saw every Claude turn kicked out of the gate and routed to a substituted OSS model paid by credits instead of served on the caller's own subscription — the opposite of what the toggle promises.

usageBypassEngaged checked req.ExcludedModels, which is the union of the customer's excluded_models policy plus hard request-time safety filters (context-overflow, gemini-unsigned-history). The customer's policy list was leaking into the pass-through decision.

Fix

Split the model-exclusion set carried on router.Request:

  • ExcludedModels (unchanged) — the full union of installation policy exclusions + request-time safety filters. The scorer continues to honor all of it.
  • SafetyExcludedModels (new) — only the request-time safety filters. The bypass gate consults this set, so a customer who opted into pass-through is served on their own subscription for models they merely deprioritized via excluded_models, while a model that literally can't accept the request (context overflow) still blocks bypass.

Wired at both dispatch sites: ProxyMessages (Anthropic) and ProxyOpenAIChatCompletion (OpenAI). The Gemini path and route-preview correctly leave the new field nil — neither engages the bypass gate.

Verified

  • wv mr tc — typecheck clean
  • wv mr t — all proxy and router tests pass, including:
    • New TestUsageBypassEngaged_SafetyExclusionBlocks_PolicyExclusionDoesNot — 3 subtests: policy exclusion bypasses, safety exclusion still blocks, and the load-bearing both-excluded case (a model on the deny list that ALSO overflows the window stays blocked, since it would 400 on the subscription too).
    • Updated TestUsageBypass_InstallationExcludedModel_StillBypasses (renamed from TestUsageBypass_ExcludedModel_EngagesRouting, asserts the new contract).
    • All existing bypass tests unchanged and passing (including TestUsageBypass_ExcludedProvider_EngagesRouting — provider exclusion is a separate check, untouched).
  • go vet ./... clean
  • gofmt -l clean

Applies universally to every installation with bypass enabled — no per-org config change.

The subscription usage-bypass gate refused to engage when the requested
model was on the installation's excluded_models list, even though the
bypass toggle ('strict pass-through until low') is an explicit opt-in
that overrides this policy exclusion. The effect: an org with bypass
turned on but a stale/broad excluded_models list saw Claude subscription
turns kicked out of the gate and routed to an OSS model paid by credits
instead of served on the caller's own subscription.

The fix splits the exclusion set carried on router.Request into two
layers:

  - ExcludedModels — the full union (installation policy + request-time
    safety filters), used by the scorer unchanged.
  - SafetyExcludedModels (new) — only the hard, request-time constraints
    a model cannot physically satisfy (context-window overflow,
    gemini-unsigned-history). The bypass gate consults this set so a
    customer who opted into pass-through is served on their own
    subscription for models they merely deprioritized via excluded_models,
    while a model that literally can't accept the request (overflow) still
    blocks bypass.

Wired at both dispatch sites: ProxyMessages (Anthropic) and
ProxyOpenAIChatCompletion (OpenAI). The Gemini path and route-preview
correctly leave the new field nil — neither engages the bypass gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @steventohme's task —— View job


  • Run git diff and scan added comment blocks
  • Flag 3+ line blocks that are too verbose
  • Post review suggestions

Posted 6 committable suggestions on 4 files. All advisory — won't block merge.

Comment thread internal/proxy/service.go Outdated

@workweave-bot workweave-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory only — comment-length nits. Won't block merge.

Comment thread internal/proxy/service.go Outdated
Comment thread internal/proxy/usage_bypass.go Outdated
Comment thread internal/proxy/usage_bypass_internal_test.go Outdated
Comment thread internal/proxy/usage_bypass_test.go Outdated
Comment thread internal/router/router.go Outdated
Comment thread internal/router/router.go Outdated
@greptile-apps

greptile-apps Bot commented Jul 20, 2026

Copy link
Copy Markdown

T-Rex T-Rex Logs

What T-Rex did

  • Reproduced the focused Go test that creates a pinned Anthropic subscription turn with the requested model in ExcludedModels and SafetyExcludedModels, and verified via the runTurnLoop that the pinned model was preserved because the short request fit the model context window.
  • Observed that ExcludedModels no longer contained the pinned model while SafetyExcludedModels still did, confirming the state transition after the safety filter re-verification.
  • Confirmed that UsageBypass remained false and the scorer was called, showing bypass was blocked by the stale SafetyExcludedModels entry after the safety filter was effectively cleared.
  • Ran and inspected the broader validation, including the focused UsageBypass tests and related package tests, and observed that the tests reported expected pass statuses (exit code 0).
  • Verified auxiliary quality checks completed cleanly, including gofmt changed-files check exit code 0, changed-packages go test OK, and go vet all clean.

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "fix(proxy): bypass engages through insta..." | Re-trigger Greptile

Comment thread internal/proxy/service.go Outdated
Cursor Bugbot caught a real gap in the first commit: SafetyExcludedModels
was built from the routing-path overflow/gemini lists, but those filters
seed the installation excluded_models set as their base and skip any model
already in it. So a requested model that is BOTH policy-excluded AND over
the context window never landed in SafetyExcludedModels — usage bypass
engaged and sent the turn on the subscription, where the same overflow
400s.

Replace safetyExcludedSet (which reused the routing lists) with
Service.safetyExcludedModels, which re-runs both filters against an EMPTY
base so overflow / gemini-unsigned are evaluated for every available model
regardless of policy exclusion. Wired at both dispatch sites.

Adds TestSafetyExcludedModels_CatchesPolicyExcludedOverflow, which
exercises the real wiring (not a hand-built set) and asserts the routing
list misses the both-excluded model while the safety set catches it.

Also applies review-bot comment-concision passes across the changed files.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @steventohme's task —— View job


  • Run git diff and scan added comment blocks
  • Flag 3+ line blocks that are too verbose
  • Post review suggestions

Posted 4 committable suggestions on 4 files. All advisory — won't block merge.

View job

@workweave-bot workweave-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory only — comment-length nits. Won't block merge.

Comment thread internal/proxy/context_overflow_internal_test.go Outdated
Comment thread internal/proxy/service.go Outdated
Comment thread internal/proxy/usage_bypass.go Outdated
Comment thread internal/proxy/usage_bypass_test.go Outdated
…t concision

Addresses PR review feedback:

- greptile P1 (defensive): runTurnLoop re-verifies an over-conservative
  context-window pin exclusion and, when the pin actually fits, prunes it
  from req.ExcludedModels. Also delete it from req.SafetyExcludedModels so
  a cleared context exclusion can't linger and refuse usage bypass for the
  pinned model. In practice the two are computed from the same
  estimate/window so the model is already absent — this makes the
  invariant explicit and robust if the fit formulas ever drift. delete on
  a nil map is a safe no-op.

- Comment-concision passes (workweave-bot) across service.go,
  usage_bypass.go, and two test files.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @steventohme's task —— View job


  • Run git diff and scan added comment blocks
  • Flag 3+ line blocks that are too verbose
  • Post review suggestions

Posted 1 committable suggestion on internal/proxy/turnloop.go. All advisory — won't block merge.

View job

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f5b2550. Configure here.

Comment thread internal/proxy/usage_bypass.go

@workweave-bot workweave-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory only — comment-length nit. Won't block merge.

@workweave-bot workweave-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory only — comment-length nit. Won't block merge.

Comment thread internal/proxy/turnloop.go Outdated
Cursor Bugbot (medium) caught a real regression from this PR: the
maxed-out loop-breaking guard in runTurnLoop adds the saturated model
only to req.ExcludedModels. Before this PR the bypass gate checked
ExcludedModels, so a re-request of the maxed subscription model was
refused and forced to route, breaking the degenerate auto-continue loop.
After the gate switched to SafetyExcludedModels, the maxed model was no
longer barred — bypass re-engaged and reopened the loop on the
subscription.

Fix: both maxed-out guard blocks (active pin + HMM history) now also add
the saturated model to req.SafetyExcludedModels via a new addToSet helper
(copy-on-write; nil-safe). The maxed exclusion is a hard loop-breaking
constraint, same class as context-overflow / gemini-unsigned, so it
belongs in the set the bypass gate honors — unlike the installation
excluded_models policy, which bypass may still override.

Adds TestUsageBypass_MaxedOutModel_EngagesRouting: a bypass-enabled
session whose pin maxed out last turn must fall through to the scorer on
re-request, not re-bypass the saturated model.

Also trims the pin-re-verify SafetyExcludedModels comment per review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @steventohme's task —— View job


Claude finished @steventohme's task —— View job


  • Run git diff and scan added comment blocks
  • Flag 3+ line blocks that are too verbose
  • Post review suggestions

Posted 3 committable suggestions on 2 files. All advisory — won't block merge.

View job

@workweave-bot workweave-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory only — comment-length nits. Won't block merge.

Comment thread internal/proxy/turnloop.go Outdated
Comment thread internal/proxy/turnloop.go Outdated
Comment thread internal/proxy/usage_bypass_test.go Outdated
Comment-concision passes (workweave-bot) on addToSet, the maxed-out
bypass guard, and TestUsageBypass_MaxedOutModel_EngagesRouting. No logic
change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @steventohme's task —— View job


  • Run git diff and scan added comment blocks
  • Flag 3+ line blocks that are too verbose
  • Post review suggestions

Posted 3 committable suggestions on 3 files. All advisory — won't block merge.

View job

@workweave-bot workweave-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory only — comment-length nits. Won't block merge.

Comment thread internal/proxy/usage_bypass_internal_test.go Outdated
Comment thread internal/proxy/usage_bypass_test.go Outdated
Comment thread internal/router/router.go Outdated
Comment-concision passes (workweave-bot) on two test docs and the
SafetyExcludedModels field comment. No logic change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @steventohme's task —— View job


Claude finished @steventohme's task —— View job


  • Run git diff and scan added comment blocks
  • Flag 3+ line blocks that are too verbose
  • Post review suggestions

No blocks worth flagging — all remaining 3+ line comment blocks are at or within the ~5-line target, and each explains a genuinely non-obvious WHY (empty-base re-run rationale, bypass gate distinction, loop-breaking constraint). No new suggestions posted.

@steventohme
steventohme merged commit d9f2067 into main Jul 20, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants