Skip to content

Conversation

@jp-agenta
Copy link
Member

[STALE] [chore] Switch sessions to connections in reads and more

Copilot AI review requested due to automatic review settings November 11, 2025 15:25
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


GitHub CI seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Comment on lines +87 to +88
return await axios
.get(`${getAgentaApiUrl()}/human-evaluations/${evaluationId}?project_id=${projectId}`)

Check failure

Code scanning / CodeQL

Server-side request forgery Critical

The
URL
of this request depends on a
user-provided value
.
The
URL
of this request depends on a
user-provided value
.
Comment on lines +74 to +76
const response = await axios.get(
`${getAgentaApiUrl()}/testsets/${testsetId}?project_id=${projectId}`,
)

Check failure

Code scanning / CodeQL

Server-side request forgery Critical test

The
URL
of this request depends on a
user-provided value
.

Copilot Autofix

AI about 1 month ago

To mitigate the SSRF risk, the code must validate and sanitize the user-provided testsetId before using it to construct internal API request URLs. The best fix would be to ensure that testsetId is in a format expected by the backend (for example, a UUID or a strict alphanumeric string), rejecting anything else before making the request. Specifically, in web/oss/src/services/testsets/api/index.ts, before using testsetId in the axios request, add a strict runtime check (using regex) to ensure its safety. If invalid, throw a controlled error or return a value indicating invalid data (mimicking the case of testsetId === null). This prevents SSRF via path traversal, malicious injection, or unwanted endpoint targeting.

Changes to be made:

  • In web/oss/src/services/testsets/api/index.ts, inside the fetchTestset function, validate testsetId using a regex for UUID or strict alphanumeric/underscore/hyphen (based on what is allowed).
  • If the validation fails, either throw an error or return the same object as when !testsetId to maintain frontend stability.

You may use a simple regex, e.g., ^[a-zA-Z0-9\-_]+$ for slugs/IDs, or a UUIDv4 regex if testset IDs are UUIDs.

No new package imports are required—use built-in JS regex.


Suggested changeset 1
web/oss/src/services/testsets/api/index.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/web/oss/src/services/testsets/api/index.ts b/web/oss/src/services/testsets/api/index.ts
--- a/web/oss/src/services/testsets/api/index.ts
+++ b/web/oss/src/services/testsets/api/index.ts
@@ -60,7 +60,13 @@
 }
 
 export const fetchTestset = async (testsetId: string | null) => {
-    if (!testsetId) {
+    // Accept only non-empty string IDs that are alphanumeric, dash, or underscore
+    const VALID_TESTSETID_REGEX = /^[a-zA-Z0-9\-_]+$/;
+    if (
+        !testsetId ||
+        typeof testsetId !== "string" ||
+        !VALID_TESTSETID_REGEX.test(testsetId)
+    ) {
         return {
             id: undefined,
             name: "No Test Set Associated",
EOF
@@ -60,7 +60,13 @@
}

export const fetchTestset = async (testsetId: string | null) => {
if (!testsetId) {
// Accept only non-empty string IDs that are alphanumeric, dash, or underscore
const VALID_TESTSETID_REGEX = /^[a-zA-Z0-9\-_]+$/;
if (
!testsetId ||
typeof testsetId !== "string" ||
!VALID_TESTSETID_REGEX.test(testsetId)
) {
return {
id: undefined,
name: "No Test Set Associated",
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR switches terminology from "sessions" to "connections" in database reads and more, involving significant refactoring across evaluation models, database migrations, authentication logic, and service layers. The changes also include cleanup of stale/deprecated code and files.

Key Changes

  • Renamed evaluation-related entities (e.g., EvaluationResultEvaluationStep, EvaluationMetricsEvaluationMetric)
  • Removed entire applications router and models files
  • Converted async database operations to sync in migration utilities
  • Removed multiple evaluation SDK test files and examples

Reviewed Changes

Copilot reviewed 119 out of 2283 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
api/oss/src/apis/fastapi/evaluations/models.py Renamed evaluation entities and updated field names
api/oss/src/apis/fastapi/applications/*.py Deleted application router, utils, and models files
api/oss/src/apis/fastapi/annotations/*.py Major rewrite of annotations router and added utils
api/oss/src/init.py Simplified blocked email/domain checking logic
api/oss/docker/Dockerfile.* Removed SDK installation and cron setup
api/oss/databases/postgres/migrations/utils.py Converted async operations to sync
api/oss/databases/postgres/migrations/tracing/versions/*.py Updated migration scripts
api/oss/databases/postgres/migrations/core/versions/*.py Deleted multiple migration files
api/oss/databases/postgres/migrations/runner.py Deleted migration runner
api/entrypoint.py Reorganized imports and router mounting
api/ee/tests/manual/evaluations/sdk/*.py Deleted all SDK test files
api/ee/src/utils/permissions.py Uncommented API key access check function
api/ee/src/services/*.py Updated service method signatures and database calls
api/ee/src/routers/*.py Changed parameter names from organization_id to org_id
api/ee/src/models/extended/*.py Renamed deprecated model classes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +102 to +103
span_type_enum = sa.Enum(SpanType, name="tracetype")
trace_type_enum = sa.Enum(TraceType, name="spantype")
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

The enum names are swapped. span_type_enum should be named 'spantype' and trace_type_enum should be named 'tracetype'. This will cause migration failures when attempting to drop these enums.

Suggested change
span_type_enum = sa.Enum(SpanType, name="tracetype")
trace_type_enum = sa.Enum(TraceType, name="spantype")
span_type_enum = sa.Enum(SpanType, name="spantype")
trace_type_enum = sa.Enum(TraceType, name="tracetype")

Copilot uses AI. Check for mistakes.
AnnotationsResponse,
AnnotationQueryRequest,
AnnotationLinkResponse,
Annotation,
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

The Annotation import is duplicated on lines 33 and 48. Remove the duplicate import to maintain clean code.

Copilot uses AI. Check for mistakes.
Comment on lines +56 to 58
from oss.src.apis.fastapi.annotations.utils import (
AnnotationFlags,
)
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

The utils module is imported twice (lines 35-39 and 56-58). Consolidate these imports into a single import block.

Copilot uses AI. Check for mistakes.
).scalar()

if (count or 0) > 0:
if count > 0:
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

The expression if count > 0 is less clear than the original if (count or 0) > 0. If count is None, this will raise a TypeError. The original code handled this case safely.

Suggested change
if count > 0:
if (count or 0) > 0:

Copilot uses AI. Check for mistakes.
Comment on lines +246 to 252
if existing_invitation is not None:
invitation = existing_invitation
elif existing_role:
else:
# Create a new invitation
invitation = await create_invitation(
existing_role, project_id, payload.email
)
else:
raise HTTPException(
status_code=404,
detail="No existing invitation found for the user",
payload.roles[0], project_id, payload.email
)
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

When no existing invitation is found, the code creates a new invitation using payload.roles[0], but the original code used existing_role from the check. If there's no existing invitation but there is an existing role assignment, this change loses that information and may create incorrect invitations.

Copilot uses AI. Check for mistakes.
status_code=409,
detail="User is already a member of the workspace",
)
raise Exception("User is already a member of the workspace")
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

Changed from HTTPException with status code 409 to a generic Exception. This breaks the API contract by removing the proper HTTP status code and makes error handling less specific for API consumers.

Copilot uses AI. Check for mistakes.
raise NoResultFound(f"User with uid {user_uid} not found")

user_org_result = await session.execute(
async with engine.core_connection() as connection:
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

The prepare=True parameter is passed to connection.execute() but this parameter doesn't exist in SQLAlchemy's execute method. This will cause runtime errors.

Copilot uses AI. Check for mistakes.
) # type: ignore
)

user_org_result = await connection.execute(stmt=stmt, prepare=True)
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

The prepare=True parameter is passed to connection.execute() but this parameter doesn't exist in SQLAlchemy's execute method. This will cause runtime errors.

Copilot uses AI. Check for mistakes.


async def _is_blocked(email: str) -> bool:
def _is_blocked(email: str) -> bool:
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

Changed from async function to sync function but the callers on lines 104, 149, 182, and 219 still use await _is_blocked(). This will cause runtime errors.

Copilot uses AI. Check for mistakes.
@junaway junaway changed the title [STALE] [chore] Switch sessions to connections in reads and more [stale] [chore] Switch sessions to connections in reads and more Nov 14, 2025
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.

3 participants