test(e2e): use CI-served models and tighten project all-team-models denial check

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Devin AI 2026-09-29 16:55:45 +00:00
parent 56b1fcabd8
commit b76730b77f
2 changed files with 20 additions and 7 deletions

View file

@ -3,9 +3,10 @@
from __future__ import annotations
import time
import warnings
from dataclasses import dataclass
from pydantic import BaseModel, ValidationError
from pydantic import BaseModel, RootModel, ValidationError
from proxy_client import ProxyClient
from e2e_http import NoBody, StreamingResponse, is_ok, unwrap
@ -32,6 +33,7 @@ TEAM_MODEL_ACCESS_DENIED_MARKER = "team_model_access_denied"
PROJECT_MODEL_ACCESS_DENIED_MARKER = "project_model_access_denied"
ROUTE_NOT_ALLOWED_MARKER = "not allowed to call this route"
ALL_TEAM_MODELS = "all-team-models"
ALL_PROXY_MODELS = "all-proxy-models"
class ApiErrorDetail(BaseModel):
@ -121,12 +123,14 @@ class AccessControlClient:
).project_id
def delete_project(self, project_id: str) -> None:
_ = self.proxy.transport.delete(
result = self.proxy.transport.delete(
"/project/delete",
headers=self.proxy.transport.master,
json=ProjectDeleteBody(project_ids=[project_id]),
response_type=NoBody,
response_type=RootModel[list[ProjectIdentity]],
)
if not is_ok(result):
warnings.warn(f"delete_project({project_id!r}) failed: {result}", stacklevel=2)
def project_key(self, team_id: str, project_id: str, models: list[str]) -> str:
return self.proxy.generate_key(KeyGenerateBody(team_id=team_id, project_id=project_id, models=models))

View file

@ -12,8 +12,10 @@ from __future__ import annotations
import pytest
from access_control_client import (
ALL_PROXY_MODELS,
ALL_TEAM_MODELS,
PROJECT_MODEL_ACCESS_DENIED_MARKER,
TEAM_MODEL_ACCESS_DENIED_MARKER,
AccessControlClient,
)
from e2e_config import unique_marker
@ -22,9 +24,8 @@ from models import ChatResponse
pytestmark = pytest.mark.e2e
TEAM_MODEL = "gpt-5.6-sol"
OUTSIDE_MODEL = "gpt-5.6-sol-eu"
ALL_PROXY_MODELS = "all-proxy-models"
TEAM_MODEL = "gemini-2.5-flash"
OUTSIDE_MODEL = "gpt-5.5"
def _chat_assert_completion(client: AccessControlClient, key: str, model: str) -> None:
@ -67,10 +68,18 @@ class TestProjectAllTeamModels:
client.set_team_models(team_id, f"e2e-proj-team-{marker}", [TEAM_MODEL])
_chat_assert_completion(client, key, TEAM_MODEL)
denied = client.chat_status(key, OUTSIDE_MODEL, f"capital of France? {unique_marker()}")
assert denied.status_code == 403 and "_model_access_denied" in denied.body, (
assert denied.status_code == 403, (
f"model outside the team's list must be denied 403, got {denied.status_code}: {denied.body[:300]}"
)
assert PROJECT_MODEL_ACCESS_DENIED_MARKER not in denied.body, (
f"the denial must come from the key or team check, not the project check: {denied.body[:300]}"
)
assert TEAM_MODEL_ACCESS_DENIED_MARKER in denied.body, (
f"403 body must be a team model-access denial, got: {denied.body[:300]}"
)
def test_project_explicit_model_list_calls_model(
self, client: AccessControlClient, resources: ResourceManager