Skip to content

LCORE-780: REST API endpoint to list all configured RAGs#805

Merged
tisnik merged 3 commits intolightspeed-core:mainfrom
tisnik:lcore-780-list-of-all-rags
Nov 18, 2025
Merged

LCORE-780: REST API endpoint to list all configured RAGs#805
tisnik merged 3 commits intolightspeed-core:mainfrom
tisnik:lcore-780-list-of-all-rags

Conversation

@tisnik
Copy link
Copy Markdown
Contributor

@tisnik tisnik commented Nov 18, 2025

Description

LCORE-780: REST API endpoint to list all configured RAGs

Type of change

  • Refactor
  • New feature
  • Bug fix
  • CVE fix
  • Optimization
  • Documentation Update
  • Configuration Update
  • Bump-up service version
  • Bump-up dependent library
  • Bump-up library or tool used for development (does not change the final image)
  • CI configuration change
  • Konflux configuration change
  • Unit tests improvement
  • Integration tests improvement
  • End to end tests improvement

Related Tickets & Documents

  • Related Issue #LCORE-780

Summary by CodeRabbit

  • New Features

    • Added an authorized GET /v1/rags endpoint to list available RAG resources.
    • Introduced a RAG list response model returning RAG identifiers.
    • Registered the new endpoint under API v1 routes.
  • Bug Fixes

    • Added robust 500 responses for configuration and connection failures when listing RAGs.
  • Tests

    • Added unit tests covering success and failure scenarios for the new endpoint.
  • Documentation

    • Updated API docs and OpenAPI spec with the new endpoint and response model.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Nov 18, 2025

Walkthrough

Adds a new authenticated GET /v1/rags endpoint, registers its router, extends the Action enum with LIST_RAGS and GET_RAG, introduces a RAGListResponse model, and adds unit tests covering success and error paths for the new endpoint.

Changes

Cohort / File(s) Change Summary
New endpoint
src/app/endpoints/rags.py
New FastAPI endpoint exposing GET /v1/rags; requires auth, validates configuration, initializes AsyncLlamaStackClientHolder, calls client.vector_stores.list(), returns RAGListResponse (list of RAG IDs), and maps connection or other exceptions to HTTP 500 responses. Exposes router, handler, and rags_responses.
Router registration
src/app/routers.py
Imported the new rags endpoint module and registered rags.router with prefix /v1 in include_routers.
Models / enums
src/models/config.py, src/models/responses.py
Added LIST_RAGS = "list_rags" and GET_RAG = "get_rag" to Action enum. Added Pydantic model RAGListResponse with rags: list[str].
Tests
tests/unit/app/endpoints/test_rags.py, tests/unit/app/test_routers.py
New unit tests for /rags covering config-missing, API connection error, generic exception, and successful retrieval; updated router-count and prefix assertions to include the new router.
Docs / OpenAPI
docs/openapi.json, docs/openapi.md, docs/output.md
Added /v1/rags GET operation and RAGListResponse schema; updated Action enum values in OpenAPI; added docs for ConversationHistoryConfiguration and removed ConversationCacheConfiguration where applicable; included examples and 200/500 responses for the new endpoint.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Endpoint as GET /v1/rags
    participant Auth as Auth Dependency
    participant Config as Config Guard
    participant Holder as AsyncLlamaStackClientHolder
    participant Llama as Llama Stack (vector_stores)

    Client->>Endpoint: GET /v1/rags
    Endpoint->>Auth: resolve auth dependency
    Auth-->>Endpoint: AuthTuple

    Endpoint->>Config: ensure configuration loaded
    Config-->>Endpoint: OK

    Endpoint->>Holder: init AsyncLlamaStackClientHolder
    Holder-->>Endpoint: async client
    Endpoint->>Llama: client.vector_stores.list()
    alt success
        Llama-->>Endpoint: list of RAG IDs
        Endpoint-->>Client: 200 RAGListResponse
    else APIConnectionError
        Llama-->>Endpoint: connection error
        Endpoint-->>Client: 500 error (connection details)
    else other error
        Llama-->>Endpoint: exception
        Endpoint-->>Client: 500 error (descriptive)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Files needing extra attention:
    • src/app/endpoints/rags.py — auth dependency usage, config guard, async client holder lifecycle, and error mapping details.
    • src/models/config.py — verify enum additions align with authorization/permission checks.
    • tests/unit/app/endpoints/test_rags.py — ensure mocks and assertions match async client behavior and error payloads.
    • docs/openapi.json — verify schema updates and examples are consistent with the new response model.

Suggested reviewers

  • asamal4
  • VladimirKadlec
  • are-ces

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding a REST API endpoint to list all configured RAGs, which aligns perfectly with the primary objective and all file changes.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/app/endpoints/rags.py (1)

23-32: Consider using standard FastAPI response format.

The current rags_responses format is non-standard. For the 200 response, consider using FastAPI's conventional format with explicit model references:

 rags_responses: dict[int | str, dict[str, Any]] = {
-    200: {
-        "rags": [
-            "vs_00000000-cafe-babe-0000-000000000000",
-            "vs_7b52a8cf-0fa3-489c-beab-27e061d102f3",
-            "vs_7b52a8cf-0fa3-489c-cafe-27e061d102f3",
-        ]
-    },
+    200: {
+        "description": "List of available RAGs",
+        "model": RAGListResponse,
+    },
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f357c3 and 2c7c0ee.

📒 Files selected for processing (4)
  • src/app/endpoints/rags.py (1 hunks)
  • src/app/routers.py (2 hunks)
  • src/models/config.py (1 hunks)
  • src/models/responses.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/app/endpoints/rags.py (7)
src/authentication/__init__.py (1)
  • get_auth_dependency (14-52)
src/authorization/middleware.py (1)
  • authorize (111-122)
src/client.py (2)
  • AsyncLlamaStackClientHolder (18-55)
  • get_client (49-55)
src/configuration.py (2)
  • configuration (73-77)
  • llama_stack_configuration (87-91)
src/models/config.py (2)
  • config (140-146)
  • Action (329-377)
src/models/responses.py (1)
  • RAGListResponse (90-101)
src/utils/endpoints.py (1)
  • check_configuration_loaded (112-124)
src/app/routers.py (1)
tests/unit/app/test_routers.py (1)
  • include_router (37-52)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build-pr
  • GitHub Check: e2e_tests (azure)
  • GitHub Check: e2e_tests (ci)
  • GitHub Check: Konflux kflux-prd-rh02 / lightspeed-stack-on-pull-request
🔇 Additional comments (4)
src/app/routers.py (1)

10-10: LGTM! Clean router integration.

The import and registration of the rags router follow the existing patterns correctly. The placement is logical—between providers and query endpoints—and maintains alphabetical order in the imports.

Also applies to: 41-41

src/models/config.py (1)

370-371: LGTM! Authorization actions added for RAG operations.

The new LIST_RAGS and GET_RAG actions are correctly defined and follow the existing naming conventions. Note that GET_RAG is currently unused in this PR—it appears to be reserved for a future endpoint to retrieve individual RAG details.

src/models/responses.py (1)

90-102: LGTM! Response model is well-defined.

The RAGListResponse model follows the established patterns in this file. The field metadata (title, description, examples) is comprehensive and the example RAG identifiers use the correct "vs_" prefix format for vector store IDs.

src/app/endpoints/rags.py (1)

35-96: LGTM! Endpoint implementation is solid.

The endpoint handler follows established patterns:

  • Proper authentication via get_auth_dependency()
  • Authorization check with @authorize(Action.LIST_RAGS)
  • Configuration validation
  • Comprehensive error handling for both connection errors and unexpected exceptions
  • Correct use of Llama Stack client's vector_stores.list() API

Minor note: The comment on line 55 "Used only by the middleware" is slightly imprecise—the auth parameter is used by both the @authorize decorator and the dependency injection system, not just middleware.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (6)
docs/openapi.md (3)

217-223: Fix markdownlint MD058 (blank lines around tables).

Add a blank line before and after the responses table.

@@
-### ✅ Responses
-
-| Status Code | Description | Component |
+### ✅ Responses
+
+| Status Code | Description | Component |
 |-------------|-------------|-----------|
 | 200 | Successful Response | [RAGListResponse](#raglistresponse) |
 | 500 | Connection to Llama Stack is broken |  |
+

990-1002: Document fields of ConversationHistoryConfiguration for clarity.

Add one‑line descriptions for type/memory/sqlite/postgres (e.g., backend selector, config blocks). Improves operator usability.


1691-1700: Add example/pattern for RAG identifiers.

Consider adding a brief note or example regex (vs_*) for rags items to set expectations for clients.

docs/openapi.json (1)

3921-3942: Polish RAGListResponse schema.

  • Prefer placing title/description at the schema level (already done) and give the property a concise title (“rags”).
  • Consider constraints: minItems: 0 and uniqueItems: true (if IDs are unique).
  • Keep examples under components.schemas.RAGListResponse.examples as a full object example.
 "RAGListResponse": {
-  "properties": {
-    "rags": {
-      "items": { "type": "string" },
-      "type": "array",
-      "title": "RAG list response",
-      "description": "List of RAG identifiers",
-      "examples": [
-        "vs_7b52a8cf-0fa3-489c-beab-27e061d102f3",
-        "vs_7b52a8cf-0fa3-489c-cafe-27e061d102f3"
-      ]
-    }
-  },
+  "properties": {
+    "rags": {
+      "type": "array",
+      "title": "rags",
+      "description": "List of RAG identifiers",
+      "items": { "type": "string" },
+      "minItems": 0,
+      "uniqueItems": true
+    }
+  },
   "type": "object",
   "required": ["rags"],
   "title": "RAGListResponse",
-  "description": "Model representing a response to list RAGs request."
+  "description": "Model representing a response to list RAGs request.",
+  "examples": [
+    { "rags": ["vs_00000000-cafe-babe-0000-000000000000"] }
+  ]
 }
docs/output.md (2)

217-223: Fix markdownlint MD058 (blank lines around tables).

Insert blank lines before/after the responses table.

@@
-### ✅ Responses
-
-| Status Code | Description | Component |
+### ✅ Responses
+
+| Status Code | Description | Component |
 |-------------|-------------|-----------|
 | 200 | Successful Response | [RAGListResponse](#raglistresponse) |
 | 500 | Connection to Llama Stack is broken |  |
+

1691-1700: Enrich RAGListResponse docs with example payload.

Add a short JSON example for clients.

@@
-| rags | array | List of RAG identifiers |
+| rags | array | List of RAG identifiers |
+
+Example:
+```json
+{ "rags": ["vs_00000000-cafe-babe-0000-000000000000"] }
+```
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3a5b198 and 2812de9.

📒 Files selected for processing (4)
  • docs/openapi.json (3 hunks)
  • docs/openapi.md (3 hunks)
  • docs/output.md (3 hunks)
  • src/app/endpoints/rags.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/endpoints/rags.py
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
docs/output.md

222-222: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)

docs/openapi.md

222-222: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build-pr
  • GitHub Check: e2e_tests (azure)
  • GitHub Check: e2e_tests (ci)
  • GitHub Check: Konflux kflux-prd-rh02 / lightspeed-stack-on-pull-request
🔇 Additional comments (2)
docs/output.md (1)

196-223: Review comment is incorrect: implementation raises different status codes than suggested.

The review suggests adding 503 and 401/403 status codes, but verification reveals:

  1. Config not loaded raises 500, not 503: check_configuration_loaded() raises HTTP_500_INTERNAL_SERVER_ERROR when configuration is None (not HTTP 503).

  2. Authorization failures raise 403, not 401: The @authorize decorator's underlying _perform_authorization_check() raises HTTP_403_FORBIDDEN for permission denials, not 401. Code reference: tests/unit/authorization/test_middleware.py line 210 confirms 403 status code for access denial.

  3. Inconsistent with similar endpoints: The /models endpoint has identical structure (@authorize decorator + check_configuration_loaded() call) but also documents only 200/500 responses, consistent with current /v1/rags documentation.

  4. Response models exist but usage is incomplete: While UnauthorizedResponse, ForbiddenResponse, and ServiceUnavailableResponse exist in the codebase, they are only imported and documented in certain endpoints like /query, not in simpler list endpoints like /models or /rags.

Either mirror the /models endpoint pattern (no auth/config response docs) or align with /query pattern (which also documents 400/403/429), but don't use the status codes suggested in this diff.

Likely an incorrect or invalid review comment.

docs/openapi.md (1)

196-223: Add 401/403 responses; note that 500→503 change requires code modifications.

The endpoint has @authorize decorator and auth dependency, so 401 and 403 responses are valid additions. However, the suggestion to document 503 for "configuration is not loaded" conflicts with actual code behavior: check_configuration_loaded() raises HTTP 500, not 503. Changing the docs to show 503 without updating the code will create a documentation-code mismatch. Either:

  • Update check_configuration_loaded() in src/utils/endpoints.py to raise HTTP_503_SERVICE_UNAVAILABLE, or
  • Keep 500 for config errors and align other endpoint docs (e.g., GET /v1/conversations) to match

Add 401 and 403 to the responses table. For the config error status code, verify whether the codebase should standardize on 503 (aligning with other endpoint docs) and update check_configuration_loaded() accordingly.

Comment on lines +321 to +350
"/v1/rags": {
"get": {
"tags": [
"rags"
],
"summary": "Rags Endpoint Handler",
"description": "Handle GET requests to list all available RAGs.\n\nRetrieves RAGs from the Llama Stack service.\n\nRaises:\n HTTPException:\n - 500 if configuration is not loaded,\n - 500 if unable to connect to Llama Stack,\n - 500 for any unexpected retrieval errors.\n\nReturns:\n RAGListResponse: List of RAGs.",
"operationId": "rags_endpoint_handler_v1_rags_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RAGListResponse"
}
}
},
"rags": [
"vs_00000000-cafe-babe-0000-000000000000",
"vs_7b52a8cf-0fa3-489c-beab-27e061d102f3",
"vs_7b52a8cf-0fa3-489c-cafe-27e061d102f3"
]
},
"500": {
"description": "Connection to Llama Stack is broken"
}
}
}
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Make 200 response example spec‑compliant and add missing 401/403 responses.

  • Move the example array under content.application/json.example (avoid top‑level “rags” alongside “content”).
  • Add 401/403 responses since the route is authenticated.
           "responses": {
             "200": {
               "description": "Successful Response",
               "content": {
                 "application/json": {
                   "schema": {
                     "$ref": "#/components/schemas/RAGListResponse"
-                  }
+                  },
+                  "example": {
+                    "rags": [
+                      "vs_00000000-cafe-babe-0000-000000000000",
+                      "vs_7b52a8cf-0fa3-489c-beab-27e061d102f3",
+                      "vs_7b52a8cf-0fa3-489c-cafe-27e061d102f3"
+                    ]
+                  }
                 }
-              },
-              "rags": [
-                "vs_00000000-cafe-babe-0000-000000000000",
-                "vs_7b52a8cf-0fa3-489c-beab-27e061d102f3",
-                "vs_7b52a8cf-0fa3-489c-cafe-27e061d102f3"
-              ]
+              }
             },
+            "401": {
+              "description": "Missing or invalid credentials provided by client",
+              "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UnauthorizedResponse" } } }
+            },
+            "403": {
+              "description": "User is not authorized",
+              "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ForbiddenResponse" } } }
+            },
             "500": {
               "description": "Connection to Llama Stack is broken"
             }
           }

Optionally add a 503 response for “configuration not loaded” to mirror other endpoints.



---

🏁 Script executed:

```shell
#!/bin/bash
# Check if /v1/rags endpoint has security requirements defined
cat docs/openapi.json | jq '.paths."/v1/rags".get' 2>/dev/null | head -50

Length of output: 969


🏁 Script executed:

#!/bin/bash
# Check if other endpoints define 401/403 responses
rg -n '"401"|"403"' docs/openapi.json | head -20

Length of output: 667


🏁 Script executed:

#!/bin/bash
# Check if UnauthorizedResponse and ForbiddenResponse schemas exist
cat docs/openapi.json | jq '.components.schemas | keys[]' 2>/dev/null | grep -i 'unauthorized\|forbidden'

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Check the overall structure of openapi.json to understand authentication patterns
cat docs/openapi.json | jq '.components.securitySchemes' 2>/dev/null

Length of output: 4


🏁 Script executed:

#!/bin/bash
# Look for other GET endpoints with 200 responses to see example placement patterns
rg -A10 '"200"' docs/openapi.json | grep -B5 -A5 'example' | head -40

Length of output: 2124


🏁 Script executed:

#!/bin/bash
# Check other GET endpoints to see if they have 401/403 responses
rg -B5 '"get"' docs/openapi.json | grep -A30 'paths' | head -60

Length of output: 500


🏁 Script executed:

#!/bin/bash
# Search source code for /rags endpoint to check if it has authentication
find . -type f \( -name "*.py" -o -name "*.js" -o -name "*.ts" \) ! -path "*/node_modules/*" ! -path "*/.git/*" | xargs grep -l 'rags' 2>/dev/null | head -5

Length of output: 137


🏁 Script executed:

#!/bin/bash
# Count total GET vs POST/PUT/DELETE endpoints and check 401/403 distribution
echo "=== GET endpoints ===" && rg -c '"get"' docs/openapi.json || echo 0
echo "=== Endpoints with 401 ===" && rg -c '"401"' docs/openapi.json || echo 0
echo "=== Endpoints with 403 ===" && rg -c '"403"' docs/openapi.json || echo 0

Length of output: 83


🏁 Script executed:

#!/bin/bash
# Check a few other GET endpoints to see their structure
rg -B2 '"get"' docs/openapi.json | grep -A50 'paths.*"get"' | head -80

Length of output: 0



---

🏁 Script executed:

```shell
#!/bin/bash
# Check the /v1/rags endpoint implementation for authentication
cat ./src/app/endpoints/rags.py

Length of output: 3102


🏁 Script executed:

#!/bin/bash
# Find a GET endpoint with 401 and check its implementation
rg -B20 '"401"' docs/openapi.json | head -30

Length of output: 1225


🏁 Script executed:

#!/bin/bash
# Identify which GET endpoints don't have 401/403
echo "=== GET endpoints without 401/403 ===" 
rg -o '"/[^"]*": {' docs/openapi.json | while read endpoint; do
  ep=$(echo "$endpoint" | sed 's/": {$//' | sed 's/^"//')
  has_401=$(rg -A50 "\"$ep\": {" docs/openapi.json | rg -c '"401"' || echo 0)
  if [ "$has_401" = "0" ]; then
    echo "$ep"
  fi
done | head -10

Length of output: 123


🏁 Script executed:

#!/bin/bash
# Check routers.py to see how /v1/rags endpoint is configured
cat ./src/app/routers.py | grep -A10 -B5 'rags'

Length of output: 1062


🏁 Script executed:

#!/bin/bash
# Check if other endpoints with check_configuration_loaded() have 503 responses
rg -l 'check_configuration_loaded' ./src/app/endpoints/*.py | head -5

Length of output: 159


🏁 Script executed:

#!/bin/bash
# Look for 503 responses in openapi.json to see if this is a documented pattern
rg -c '"503"' docs/openapi.json

Length of output: 1


🏁 Script executed:

#!/bin/bash
# Check what responses are documented for endpoints that use check_configuration_loaded
cat ./src/app/endpoints/models.py | grep -A50 '@router.get'

Length of output: 1717


🏁 Script executed:

#!/bin/bash
# Check models_responses definition to see if it includes 503 for configuration error
cat ./src/app/endpoints/models.py | grep -B5 -A20 'models_responses'

Length of output: 1619


🏁 Script executed:

#!/bin/bash
# Check the openapi.json spec for /v1/models endpoint responses
cat docs/openapi.json | jq '.paths."/v1/models".get.responses' 2>/dev/null | head -40

Length of output: 885


🏁 Script executed:

#!/bin/bash
# Compare rags responses vs models responses in openapi.json
echo "=== /v1/rags responses ===" && cat docs/openapi.json | jq '.paths."/v1/rags".get.responses | keys' 2>/dev/null
echo "=== /v1/models responses ===" && cat docs/openapi.json | jq '.paths."/v1/models".get.responses | keys' 2>/dev/null

Length of output: 97


Fix example placement per OpenAPI spec and add missing 401/403 authentication responses.

The /v1/rags endpoint is authenticated (decorator @authorize(Action.LIST_RAGS) + auth dependency), but the OpenAPI spec lacks 401/403 responses. The example array currently violates the spec by sitting at the response level as a sibling to "content"—it must move under content.application/json.example.

           "responses": {
             "200": {
               "description": "Successful Response",
               "content": {
                 "application/json": {
                   "schema": {
                     "$ref": "#/components/schemas/RAGListResponse"
-                  }
+                  },
+                  "example": {
+                    "rags": [
+                      "vs_00000000-cafe-babe-0000-000000000000",
+                      "vs_7b52a8cf-0fa3-489c-beab-27e061d102f3",
+                      "vs_7b52a8cf-0fa3-489c-cafe-27e061d102f3"
+                    ]
+                  }
                 }
-              },
-              "rags": [
-                "vs_00000000-cafe-babe-0000-000000000000",
-                "vs_7b52a8cf-0fa3-489c-beab-27e061d102f3",
-                "vs_7b52a8cf-0fa3-489c-cafe-27e061d102f3"
-              ]
+              }
             },
+            "401": {
+              "description": "Missing or invalid credentials provided by client",
+              "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UnauthorizedResponse" } } }
+            },
+            "403": {
+              "description": "User is not authorized",
+              "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ForbiddenResponse" } } }
+            },
             "500": {
               "description": "Connection to Llama Stack is broken"
             }
           }
🤖 Prompt for AI Agents
In docs/openapi.json around lines 321 to 350, the responses section for GET
/v1/rags places an example array incorrectly as a sibling to "content" and omits
authentication responses; move the example array into
content.application/json.example (or content.application/json.examples) under
the 200 response schema so it complies with OpenAPI, and add 401 and 403
response objects (with brief descriptions and optional content/schema refs) to
reflect the endpoint's authentication requirements; ensure JSON structure
remains valid (no duplicate keys) and update operationId/tags only if needed.

Comment on lines +1620 to 1622
"list_rags",
"get_rag",
"get_metrics",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Confirm authorization rules include new actions.

You added Action enum values list_rags/get_rag. Please verify the authorization config and any default role mappings allow intended roles to call /v1/rags.


🏁 Script executed:

#!/bin/bash
# Inspect repo for access rules mentioning list_rags/get_rag
rg -nP 'list_rags|get_rag|LIST_RAGS|GET_RAG' -C3

Length of output: 10398


I need to search for the GET_RAG endpoint authorization and role mapping configuration to complete the verification.

I need to search the codebase more specifically for GET_RAG endpoint and authorization configuration files.


Wait, I need to run scripts against the actual repo. Let me correct that:




🏁 Script executed:

#!/bin/bash
# Find GET_RAG endpoint handler and authorization config files
echo "=== Searching for GET_RAG endpoint ==="
rg -nP '@authorize\(Action\.GET_RAG\)|def.*get_rag|GET_RAG.*endpoint' -A2 -B2

echo "=== Looking for authorization/role config files ==="
fd -e yaml -e yml -e json -e toml -e py | rg -i 'auth|role|permission|config' | head -20

echo "=== Checking rags.py file for all endpoints ==="
cat src/app/endpoints/rags.py 2>/dev/null | head -100

Length of output: 5199


🏁 Script executed:

#!/bin/bash
# Find GET_RAG endpoint handler and authorization config files
echo "=== Searching for GET_RAG endpoint ==="
rg -nP '@authorize\(Action\.GET_RAG\)|def.*get_rag.*(' -A2 -B2

echo "=== Searching full rags.py for all endpoint definitions ==="
rg -n 'def.*endpoint|@router\.(get|post)' src/app/endpoints/rags.py -A3

echo "=== Looking for authorization config files ==="
fd '(auth|permission|role)' --type f | head -20

Length of output: 1024



---

🏁 Script executed:

```shell
#!/bin/bash
# Check authorization middleware and role configuration
echo "=== Checking authorization middleware ==="
cat src/authorization/middleware.py | head -80

echo "=== Checking authorization resolvers ==="
cat src/authorization/resolvers.py | head -80

echo "=== Searching for role mappings or action lists ==="
rg -n 'LIST_RAGS|GET_RAG' src/authorization/ -B2 -A2

Length of output: 5243



---

🏁 Script executed:

```shell
#!/bin/bash
# Search for access_rules configuration and GET_RAG endpoint
echo "=== Searching for access_rules in configuration ==="
rg -n 'access_rules|AccessRule' src/ --type py -B2 -A2 | head -60

echo "=== Search for any GET_RAG endpoint definition (including comments) ==="
rg -n 'get.*rag|GET_RAG' src/app/endpoints/ -B3 -A3

echo "=== Check models/config.py for AccessRule and default mappings ==="
rg -n 'class AccessRule|access_rule' src/models/config.py -B2 -A8

Length of output: 6810



---

🏁 Script executed:

```shell
#!/bin/bash
# Check openapi.json to understand GET_RAG endpoint specification
echo "=== Looking at openapi.json around GET_RAG action ==="
rg -n 'get_rag|GET_RAG' docs/openapi.json -B5 -A5 | head -100

echo "=== Search for any endpoint path definitions in openapi.json for rags ==="
rg -n '/rags' docs/openapi.json -B2 -A10 | head -80

Length of output: 1335


GET_RAG endpoint is missing implementation.

LIST_RAGS is properly authorized with @authorize(Action.LIST_RAGS) on the /v1/rags GET endpoint. However, GET_RAG is declared in the Action enum and listed in openapi.json as an allowed action, but there is no corresponding endpoint implementation (no GET /v1/rags/{rag_id} endpoint found). This creates a spec-to-code inconsistency where an action is declared without an endpoint to back it.

Additionally, authorization defaults to NoopAccessResolver when no access_rules are explicitly configured, which permits all roles. Ensure access_rules are properly configured if authentication is required.

🤖 Prompt for AI Agents
In docs/openapi.json around lines 1620-1622, the Action enum lists "get_rag" but
there is no corresponding GET /v1/rags/{rag_id} endpoint implementation; add a
new GET /v1/rags/{rag_id} route handler that fetches a single RAG by id,
validates and parses the rag_id path parameter, returns 200 with the RAG schema
or 404 if not found, and apply the same authorization decorator used for
LIST_RAGS (e.g., @authorize(Action.GET_RAG)) so the OpenAPI spec and code match;
alternatively, if a single-RAG GET is not required, remove "get_rag" from the
Action enum and openapi.json; finally, ensure access_rules are configured (not
left as NoopAccessResolver) if authentication/authorization is required.

@tisnik tisnik merged commit e489990 into lightspeed-core:main Nov 18, 2025
21 of 23 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.

1 participant