test(e2e): pin teamless all-team-models key to full proxy access

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
mateo 2026-07-07 20:24:37 +00:00
parent a43f128a74
commit 16e8a5c33a
4 changed files with 62 additions and 0 deletions

View file

@ -17,6 +17,7 @@ from models import (
MODEL_ACCESS_DENIED_MARKER = "key_model_access_denied"
ROUTE_NOT_ALLOWED_MARKER = "not allowed to call this route"
ALL_TEAM_MODELS_SENTINEL = "all-team-models"
@dataclass(frozen=True, slots=True)

View file

@ -19,6 +19,7 @@ import pytest
from access_control_client import (
AccessControlClient,
ALL_TEAM_MODELS_SENTINEL,
MODEL_ACCESS_DENIED_MARKER,
ROUTE_NOT_ALLOWED_MARKER,
)
@ -29,6 +30,7 @@ pytestmark = pytest.mark.e2e
ALLOWED_MODEL = "gemini-2.5-flash"
DISALLOWED_MODEL = "gpt-5.5"
PROXY_CHAT_MODELS = frozenset({"gpt-5.5", "claude-haiku-4-5", "gemini-2.5-flash"})
def _is_json(body: str) -> bool:
@ -81,3 +83,38 @@ class TestAccessControl:
f"{result.status_code}: {result.body[:300]}"
)
assert _is_json(result.body), f"400 body must be valid JSON: {result.body[:300]}"
class TestTeamlessAllTeamModels:
"""A key scoped to ``all-team-models`` with no team assigned inherits the
full proxy model list, exactly as if its models field were left empty. This
is the intended contract (GH #30737): #29746 tightened it to deny such keys
and was reverted in #32032. These cases pin both surfaces a client touches,
listing (GET /v1/models) and calling (/chat/completions), so re-introducing
the team_id guard on either path fails here."""
def test_teamless_all_team_models_key_lists_all_proxy_models(
self, client: AccessControlClient, resources: ResourceManager
) -> None:
key = resources.key(models=[ALL_TEAM_MODELS_SENTINEL])
listed = set(client.gateway.list_models(key))
assert PROXY_CHAT_MODELS <= listed, (
f"teamless {ALL_TEAM_MODELS_SENTINEL!r} key must list every proxy model, "
f"missing {PROXY_CHAT_MODELS - listed}; got {sorted(listed)}"
)
assert ALL_TEAM_MODELS_SENTINEL not in listed, (
f"the {ALL_TEAM_MODELS_SENTINEL!r} sentinel must expand to real models, "
f"never surface as a listed model; got {sorted(listed)}"
)
def test_teamless_all_team_models_key_can_call_any_model(
self, client: AccessControlClient, resources: ResourceManager
) -> None:
key = resources.key(models=[ALL_TEAM_MODELS_SENTINEL])
result = client.chat_status(
key, ALLOWED_MODEL, f"capital of France? {unique_marker()}"
)
assert result.status_code == 200, (
f"teamless {ALL_TEAM_MODELS_SENTINEL!r} key must be allowed to call "
f"{ALLOWED_MODEL!r}, got {result.status_code}: {result.body[:300]}"
)

View file

@ -39,6 +39,7 @@ from models import (
ModelInfoBody,
ModelInfoEntry,
ModelInfoResponse,
ModelListResponse,
ModelMode,
ModelNewBody,
ModelNewResponse,
@ -119,6 +120,21 @@ class Gateway:
)
).data
def list_models(self, key: str) -> list[str]:
"""The public model names GET /v1/models lists as callable for `key`,
the same visibility an OpenAI-compatible client (e.g. OpenWebUI) sees."""
return [
entry.id
for entry in unwrap(
self.transport.get(
"/v1/models",
headers=self.transport.bearer(key),
params=NoBody(),
response_type=ModelListResponse,
)
).data
]
def create_model(
self,
model_name: str,

View file

@ -336,6 +336,14 @@ class ModelInfoResponse(BaseModel):
data: list[ModelInfoEntry] = []
class ModelListEntry(BaseModel):
id: str
class ModelListResponse(BaseModel):
data: list[ModelListEntry] = []
class FileEntry(BaseModel):
id: str