Skip to content

Add nutrient endpoint#131

Open
paulwiese wants to merge 1 commit into
mainfrom
feat/generate-nutrients
Open

Add nutrient endpoint#131
paulwiese wants to merge 1 commit into
mainfrom
feat/generate-nutrients

Conversation

@paulwiese

@paulwiese paulwiese commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Added endpoint ai/nutrients with same specification publicly and internally.
Added instructions to use abbreviations for units in the system prompt.

Type of change

  • Bug fix
  • New feature
  • Refactor / cleanup
  • Infrastructure / CI
  • Documentation

API changes

  • This PR does not affect the API
  • This PR changes the API → api/openapi.yaml updated and api/scripts/gen-all.sh re-run

Definition of Done

  • CI passes
  • Pre-commit hooks pass locally
  • Relevant tests added or updated

Summary by CodeRabbit

  • New Features

    • Added an authenticated AI endpoint for generating recipe nutrition information.
    • Requests include a recipe and optional language; successful responses provide calories, protein, fat, and carbohydrates.
    • Added synchronous and asynchronous client support across supported services.
    • Added validation and handling for authorization failures, invalid requests, timeouts, and unavailable AI responses.
  • Bug Fixes

    • Improved recipe-generation instructions to use consistent lowercase abbreviated measurement units.

@paulwiese paulwiese deployed to kubernetes July 10, 2026 21:49 — with GitHub Actions Active
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds POST /ai/nutrients across OpenAPI contracts, Python services and clients, Spring integrations, and the web client. The flow validates signed requests, invokes structured nutrient generation, forwards responses, and exposes typed request and response models.

Changes

AI nutrient generation

Layer / File(s) Summary
Nutrient API contracts
api/openapi*.yaml, web-client/src/api.ts, services/spring-api/.../model/NutrientRequest.kt
Defines public and internal nutrient endpoints, request schemas, authentication headers, response types, and web-client models.
Python nutrient generation
services/py-recipe-service/main.py, services/py-recipe-service/tests/*
Adds the signed FastAPI endpoint, structured LLM invocation, error handling, prompt unit guidance, and endpoint tests.
Generated Python clients
services/py-*/client/cooking_assistant_gen_ai_services_api_internal_client/...
Adds forwarded request models and synchronous/asynchronous internal nutrient endpoint clients with typed response parsing.
Spring nutrient integration
services/spring-api/src/main/kotlin/org/openapitools/api/AIApi*, .../internal/client/*, .../internal/model/*
Adds the Spring endpoint, forwards nutrient requests to the recipe service, maps nutrient responses, and registers generated models.
Generated Spring source updates
services/spring-api/src/main/kotlin/org/openapitools/{api,model}/*
Reformats generated configuration, API, exception, and model sources while preserving existing behavior and model semantics.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant SpringAPI
  participant RecipeService
  participant LLM
  Client->>SpringAPI: POST /ai/nutrients
  SpringAPI->>RecipeService: Forward signed nutrient request
  RecipeService->>LLM: Generate structured nutrients
  LLM-->>RecipeService: RecipeNutrients
  RecipeService-->>SpringAPI: RecipeNutrients
  SpringAPI-->>Client: RecipeNutrients response
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.63% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding the nutrient endpoint.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/generate-nutrients

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.

@github-actions

Copy link
Copy Markdown

🚀 Frontend preview ↗  ·  commit 186c6fd96612948cb88f022a6a78833b06f72129

@paulwiese paulwiese requested review from imol-ai and jschoedl July 10, 2026 21:51

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🧹 Nitpick comments (10)
services/spring-api/src/main/kotlin/org/openapitools/model/AuthResponse.kt (1)

25-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid the empty generated class body.

Detekt reports EmptyClassBlock for this body. Remove the braces, update the generator template, or exclude generated sources from this rule to avoid lint warnings.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/spring-api/src/main/kotlin/org/openapitools/model/AuthResponse.kt`
around lines 25 - 27, The generated AuthResponse class has an empty body
triggering Detekt’s EmptyClassBlock warning. Update the generator template
producing AuthResponse to omit the empty braces, or configure Detekt to exclude
generated sources from this rule.

Source: Linters/SAST tools

services/spring-api/src/main/kotlin/org/openapitools/model/AuthRequest.kt (1)

31-33: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid the empty generated class body.

Detekt reports EmptyClassBlock for this body. Remove the braces, update the generator template, or exclude generated sources from this rule to avoid lint warnings.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/spring-api/src/main/kotlin/org/openapitools/model/AuthRequest.kt`
around lines 31 - 33, Remove the empty class body from the generated AuthRequest
declaration, or update the generator template that produces it so empty classes
use no braces; alternatively configure Detekt to exclude generated sources from
EmptyClassBlock checks.

Source: Linters/SAST tools

services/spring-api/src/main/kotlin/org/openapitools/model/UserProfileUpdate.kt (1)

37-39: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid the empty generated class body.

Detekt reports EmptyClassBlock for this body. Remove the braces, update the generator template, or exclude generated sources from this rule to avoid lint warnings.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@services/spring-api/src/main/kotlin/org/openapitools/model/UserProfileUpdate.kt`
around lines 37 - 39, The generated UserProfileUpdate class has an empty body
that triggers Detekt’s EmptyClassBlock rule. Remove the empty braces from
UserProfileUpdate, preferably by correcting the generator template, or configure
Detekt to exclude generated sources.

Source: Linters/SAST tools

services/spring-api/src/main/kotlin/org/openapitools/model/ErrorResponse.kt (1)

25-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid the empty generated class body.

Detekt reports EmptyClassBlock for this body. Remove the braces, update the generator template, or exclude generated sources from this rule to avoid lint warnings.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/spring-api/src/main/kotlin/org/openapitools/model/ErrorResponse.kt`
around lines 25 - 27, Remove the empty class body in ErrorResponse by using a
declaration without braces, and update the generator template that produces this
model so future generated classes follow the same form; alternatively, configure
Detekt to exclude generated sources from EmptyClassBlock.

Source: Linters/SAST tools

services/spring-api/src/main/kotlin/org/openapitools/model/UserProfile.kt (1)

31-33: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid the empty generated class body.

Detekt reports EmptyClassBlock for this body. Remove the braces, update the generator template, or exclude generated sources from this rule to avoid lint warnings.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/spring-api/src/main/kotlin/org/openapitools/model/UserProfile.kt`
around lines 31 - 33, Remove the empty class body from UserProfile and update
the source generator template producing it so generated models use the
brace-free declaration; alternatively, configure Detekt to exclude generated
sources from EmptyClassBlock.

Source: Linters/SAST tools

services/spring-api/src/main/kotlin/org/openapitools/model/RecipeUpdate.kt (1)

48-50: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the empty class body or exclude generated models from detekt.

RecipeUpdate has no body members, and detekt reports empty-blocks.EmptyClassBlock. Apply the fix in the generator/template, or exclude generated sources from this rule.

Proposed fix
-) {
-
-}
+)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/spring-api/src/main/kotlin/org/openapitools/model/RecipeUpdate.kt`
around lines 48 - 50, RecipeUpdate has an empty class body that triggers
detekt’s EmptyClassBlock rule. Fix the model generator/template to omit the
empty body for memberless generated classes, or configure detekt to exclude
generated model sources from this rule.

Source: Linters/SAST tools

services/spring-api/src/main/kotlin/org/openapitools/model/RecipeRequest.kt (1)

33-35: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the empty class body or exclude generated models from detekt.

RecipeRequest has no body members, but the explicit {} triggers detekt’s empty-blocks.EmptyClassBlock warning. Fix this in the generator/template or exclude generated sources.

Proposed fix
-) {
-
-}
+)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/spring-api/src/main/kotlin/org/openapitools/model/RecipeRequest.kt`
around lines 33 - 35, Remove the empty class body from the generated
RecipeRequest declaration, or update the generator/template responsible for
RecipeRequest to omit {} for empty models; alternatively configure detekt to
exclude generated model sources, including RecipeRequest.

Source: Linters/SAST tools

services/spring-api/src/main/kotlin/org/openapitools/model/UserCredentials.kt (1)

31-33: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the empty class body or exclude generated models from detekt.

UserCredentials has no body members, while detekt reports empty-blocks.EmptyClassBlock. Fix the generator/template or exclude generated sources from this rule.

Proposed fix
-) {
-
-}
+)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@services/spring-api/src/main/kotlin/org/openapitools/model/UserCredentials.kt`
around lines 31 - 33, Address the detekt EmptyClassBlock violation for
UserCredentials by updating the model generator/template to omit the empty class
body, or configure detekt to exclude generated model sources from this rule.
Prefer the generator/template fix if these files are regenerated.

Source: Linters/SAST tools

services/spring-api/src/main/kotlin/org/openapitools/model/RecipeNutrients.kt (1)

40-42: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the empty class body or exclude generated models from detekt.

RecipeNutrients has no members in its body, and detekt reports empty-blocks.EmptyClassBlock. Remove {} in the generator/template, or configure generated sources to be excluded from this rule.

Proposed fix
-) {
-
-}
+)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@services/spring-api/src/main/kotlin/org/openapitools/model/RecipeNutrients.kt`
around lines 40 - 42, Resolve the detekt EmptyClassBlock violation for
RecipeNutrients by removing its empty class body in the generator/template, or
excluding generated model sources from this detekt rule; prefer the
generator/template change so generated models no longer emit empty braces.

Source: Linters/SAST tools

services/spring-api/src/main/kotlin/org/openapitools/model/HelpRequest.kt (1)

31-33: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the explicit empty class body from generated models.

Detekt flags this empty body. Remove it in the generator/template rather than retaining {} across regenerated model classes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/spring-api/src/main/kotlin/org/openapitools/model/HelpRequest.kt`
around lines 31 - 33, Remove the explicit empty class body from the
generator/template that produces HelpRequest and other generated model classes,
ensuring generated declarations end without empty braces and remain
Detekt-compliant after regeneration.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api/openapi.yaml`:
- Around line 756-766: Resolve the mismatch for NutrientRequest.language: either
remove the language property and its description from the OpenAPI
NutrientRequest schema, or propagate it through AIApiController into the Python
nutrient-generation request and incorporate it into the prompt construction in
main.py. Keep the schema, internal request model, controller forwarding, and
prompt behavior consistent.

In
`@services/py-help-service/client/cooking_assistant_gen_ai_services_api_internal_client/api/recipe_service/post_ai_nutrients.py`:
- Around line 72-80: The `_build_response` function converts every HTTP status
to `HTTPStatus`, which fails for non-standard codes before unexpected-status
handling runs. Preserve `response.status_code` as a raw integer in the
`Response` construction, or update `Response.status_code` to accept arbitrary
integers while maintaining the existing `raise_on_unexpected_status` and
`UnexpectedStatus` behavior.

In `@services/spring-api/src/main/kotlin/org/openapitools/api/AIApiController.kt`:
- Around line 101-121: Preserve NutrientRequest.language when forwarding
requests from aiNutrientsPost: add a corresponding language field to
NutrientRequestForwarded and populate it from nutrientRequest.language when
constructing the internal request. If language is intentionally unsupported,
remove it from the public NutrientRequest model instead.

---

Nitpick comments:
In `@services/spring-api/src/main/kotlin/org/openapitools/model/AuthRequest.kt`:
- Around line 31-33: Remove the empty class body from the generated AuthRequest
declaration, or update the generator template that produces it so empty classes
use no braces; alternatively configure Detekt to exclude generated sources from
EmptyClassBlock checks.

In `@services/spring-api/src/main/kotlin/org/openapitools/model/AuthResponse.kt`:
- Around line 25-27: The generated AuthResponse class has an empty body
triggering Detekt’s EmptyClassBlock warning. Update the generator template
producing AuthResponse to omit the empty braces, or configure Detekt to exclude
generated sources from this rule.

In `@services/spring-api/src/main/kotlin/org/openapitools/model/ErrorResponse.kt`:
- Around line 25-27: Remove the empty class body in ErrorResponse by using a
declaration without braces, and update the generator template that produces this
model so future generated classes follow the same form; alternatively, configure
Detekt to exclude generated sources from EmptyClassBlock.

In `@services/spring-api/src/main/kotlin/org/openapitools/model/HelpRequest.kt`:
- Around line 31-33: Remove the explicit empty class body from the
generator/template that produces HelpRequest and other generated model classes,
ensuring generated declarations end without empty braces and remain
Detekt-compliant after regeneration.

In
`@services/spring-api/src/main/kotlin/org/openapitools/model/RecipeNutrients.kt`:
- Around line 40-42: Resolve the detekt EmptyClassBlock violation for
RecipeNutrients by removing its empty class body in the generator/template, or
excluding generated model sources from this detekt rule; prefer the
generator/template change so generated models no longer emit empty braces.

In `@services/spring-api/src/main/kotlin/org/openapitools/model/RecipeRequest.kt`:
- Around line 33-35: Remove the empty class body from the generated
RecipeRequest declaration, or update the generator/template responsible for
RecipeRequest to omit {} for empty models; alternatively configure detekt to
exclude generated model sources, including RecipeRequest.

In `@services/spring-api/src/main/kotlin/org/openapitools/model/RecipeUpdate.kt`:
- Around line 48-50: RecipeUpdate has an empty class body that triggers detekt’s
EmptyClassBlock rule. Fix the model generator/template to omit the empty body
for memberless generated classes, or configure detekt to exclude generated model
sources from this rule.

In
`@services/spring-api/src/main/kotlin/org/openapitools/model/UserCredentials.kt`:
- Around line 31-33: Address the detekt EmptyClassBlock violation for
UserCredentials by updating the model generator/template to omit the empty class
body, or configure detekt to exclude generated model sources from this rule.
Prefer the generator/template fix if these files are regenerated.

In `@services/spring-api/src/main/kotlin/org/openapitools/model/UserProfile.kt`:
- Around line 31-33: Remove the empty class body from UserProfile and update the
source generator template producing it so generated models use the brace-free
declaration; alternatively, configure Detekt to exclude generated sources from
EmptyClassBlock.

In
`@services/spring-api/src/main/kotlin/org/openapitools/model/UserProfileUpdate.kt`:
- Around line 37-39: The generated UserProfileUpdate class has an empty body
that triggers Detekt’s EmptyClassBlock rule. Remove the empty braces from
UserProfileUpdate, preferably by correcting the generator template, or configure
Detekt to exclude generated sources.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 57555deb-0395-4d5e-9181-b1ce73604c13

📥 Commits

Reviewing files that changed from the base of the PR and between d36458b and 186c6fd.

📒 Files selected for processing (41)
  • api/openapi-internal.yaml
  • api/openapi.yaml
  • services/py-help-service/client/cooking_assistant_gen_ai_services_api_internal_client/api/recipe_service/post_ai_nutrients.py
  • services/py-help-service/client/cooking_assistant_gen_ai_services_api_internal_client/models/__init__.py
  • services/py-help-service/client/cooking_assistant_gen_ai_services_api_internal_client/models/nutrient_request_forwarded.py
  • services/py-help-service/client/pyproject.toml
  • services/py-recipe-service/client/cooking_assistant_gen_ai_services_api_internal_client/api/recipe_service/post_ai_nutrients.py
  • services/py-recipe-service/client/cooking_assistant_gen_ai_services_api_internal_client/models/__init__.py
  • services/py-recipe-service/client/cooking_assistant_gen_ai_services_api_internal_client/models/nutrient_request_forwarded.py
  • services/py-recipe-service/client/pyproject.toml
  • services/py-recipe-service/main.py
  • services/py-recipe-service/tests/test_recipe_service.py
  • services/spring-api/.openapi-generator/FILES
  • services/spring-api/src/main/kotlin/org/openapitools/SpringDocConfiguration.kt
  • services/spring-api/src/main/kotlin/org/openapitools/api/AIApi.kt
  • services/spring-api/src/main/kotlin/org/openapitools/api/AIApiController.kt
  • services/spring-api/src/main/kotlin/org/openapitools/api/ApiUtil.kt
  • services/spring-api/src/main/kotlin/org/openapitools/api/Exceptions.kt
  • services/spring-api/src/main/kotlin/org/openapitools/api/RecipesApi.kt
  • services/spring-api/src/main/kotlin/org/openapitools/api/UsersApi.kt
  • services/spring-api/src/main/kotlin/org/openapitools/internal/client/RecipeServiceApi.kt
  • services/spring-api/src/main/kotlin/org/openapitools/internal/model/NutrientRequestForwarded.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/AuthRequest.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/AuthResponse.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/ErrorResponse.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/HelpRequest.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/HelpResponse.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/Language.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/NutrientRequest.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/Recipe.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/RecipeCreated.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/RecipeIngredient.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/RecipeInput.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/RecipeNutrients.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/RecipeRequest.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/RecipeUpdate.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/UserCredentials.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/UserPreferences.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/UserProfile.kt
  • services/spring-api/src/main/kotlin/org/openapitools/model/UserProfileUpdate.kt
  • web-client/src/api.ts

Comment thread api/openapi.yaml
Comment on lines +756 to +766

NutrientRequest:
type: object
required: [recipe]
additionalProperties: false
properties:
recipe:
$ref: "#/components/schemas/RecipeInput"
language:
$ref: '#/components/schemas/Language'
description: Optional active language context for any generated metadata text

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if the Python nutrient endpoint accepts or uses a language parameter
rg -n -C3 'language' --type py services/py-recipe-service/main.py | head -40

Repository: AET-DevOps26/team-devsecops

Length of output: 1432


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== openapi schema around NutrientRequest =="
sed -n '748,776p' api/openapi.yaml

echo
echo "== controller references =="
rg -n -C4 'NutrientRequestForwarded|language|RecipeNutrients|NutrientRequest' api src services -g '!**/node_modules/**' | head -200

echo
echo "== python service context around language usage =="
sed -n '200,240p' services/py-recipe-service/main.py

Repository: AET-DevOps26/team-devsecops

Length of output: 11338


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== internal nutrient schema =="
sed -n '348,366p' api/openapi-internal.yaml

echo
echo "== nutrient controller / forwarding code =="
fd -a 'AIApiController.kt|*Controller.kt|*nutrient*' services src api

Repository: AET-DevOps26/team-devsecops

Length of output: 941


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== controller location =="
fd -a 'AIApiController.kt' .

echo
echo "== controller references to nutrient request =="
rg -n -C4 'NutrientRequestForwarded|NutrientRequest|nutrient|language' services/spring-api -g '*.kt' -g '*.yaml' -g '*.md'

echo
echo "== python service nutrient route/model context =="
rg -n -C4 'nutrient|Nutrient|language' services/py-recipe-service/main.py

Repository: AET-DevOps26/team-devsecops

Length of output: 50383


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== nutrient handler in python service =="
rg -n -C6 'ai/nutrients|nutrient|Nutrient|RecipeNutrients|language' services/py-recipe-service/main.py

echo
echo "== targeted slice around the nutrient route if present =="
python3 - <<'PY'
from pathlib import Path
p = Path('services/py-recipe-service/main.py')
text = p.read_text()
for key in ['`@app.post`("/ai/nutrients")', 'def ai_nutrients', 'def calculate_nutrients', 'NutrientRequest', 'RecipeNutrients']:
    idx = text.find(key)
    if idx != -1:
        start = max(0, text.rfind('\n', 0, idx-300))
        end = min(len(text), text.find('\n\n', idx+1) + 2 if text.find('\n\n', idx+1) != -1 else idx+2000)
        print(f'--- around {key} ---')
        print(text[start:end])
PY

Repository: AET-DevOps26/team-devsecops

Length of output: 5331


language is ignored in nutrient generation.
api/openapi.yaml documents it as affecting generated metadata text, but services/spring-api/src/main/kotlin/org/openapitools/api/AIApiController.kt forwards only recipe, and services/py-recipe-service/main.py builds the nutrient prompt from the recipe alone. Either remove language from NutrientRequest, or thread it through the internal request and prompt if it’s meant to matter.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/openapi.yaml` around lines 756 - 766, Resolve the mismatch for
NutrientRequest.language: either remove the language property and its
description from the OpenAPI NutrientRequest schema, or propagate it through
AIApiController into the Python nutrient-generation request and incorporate it
into the prompt construction in main.py. Keep the schema, internal request
model, controller forwarding, and prompt behavior consistent.

Comment on lines +72 to +80
def _build_response(
*, client: AuthenticatedClient | Client, response: httpx.Response
) -> Response[ErrorResponse | RecipeNutrients]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C3 'HTTPStatus\(response\.status_code\)|class Response' services/py-help-service/client

Repository: AET-DevOps26/team-devsecops

Length of output: 5750


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the shared response type and the parse/error path.
sed -n '1,220p' services/py-help-service/client/cooking_assistant_gen_ai_services_api_internal_client/types.py
printf '\n--- post_ai_nutrients.py ---\n'
sed -n '1,220p' services/py-help-service/client/cooking_assistant_gen_ai_services_api_internal_client/api/recipe_service/post_ai_nutrients.py
printf '\n--- post_ai_help.py ---\n'
sed -n '1,220p' services/py-help-service/client/cooking_assistant_gen_ai_services_api_internal_client/api/help_service/post_ai_help.py
printf '\n--- get_health.py ---\n'
sed -n '1,180p' services/py-help-service/client/cooking_assistant_gen_ai_services_api_internal_client/api/help_service/get_health.py

printf '\n--- grep UnexpectedStatus / raise_on_unexpected_status ---\n'
rg -n -C2 'UnexpectedStatus|raise_on_unexpected_status|HTTPStatus\(' services/py-help-service/client/cooking_assistant_gen_ai_services_api_internal_client

Repository: AET-DevOps26/team-devsecops

Length of output: 42600


Preserve raw status codes in _build_response.

HTTPStatus(response.status_code) can raise ValueError for non-standard responses like 599, which bypasses the documented raise_on_unexpected_status / UnexpectedStatus path. Keep the raw int here, or relax Response.status_code to accept int.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@services/py-help-service/client/cooking_assistant_gen_ai_services_api_internal_client/api/recipe_service/post_ai_nutrients.py`
around lines 72 - 80, The `_build_response` function converts every HTTP status
to `HTTPStatus`, which fails for non-standard codes before unexpected-status
handling runs. Preserve `response.status_code` as a raw integer in the
`Response` construction, or update `Response.status_code` to accept arbitrary
integers while maintaining the existing `raise_on_unexpected_status` and
`UnexpectedStatus` behavior.

Comment on lines +101 to +121
override fun aiNutrientsPost(
@Valid nutrientRequest: org.openapitools.model.NutrientRequest,
): ResponseEntity<org.openapitools.model.RecipeNutrients> {
val internalRequest =
org.openapitools.internal.model.NutrientRequestForwarded(
recipe = nutrientRequest.recipe.toInternalRecipe(),
)

val retrofitResponse =
try {
recipeServiceApi.aiNutrientsPost("", "", internalRequest).execute()
} catch (e: InterruptedIOException) {
throw ResponseStatusException(HttpStatus.GATEWAY_TIMEOUT, "Upstream AI service timed out", e)
} catch (e: Exception) {
throw ResponseStatusException(HttpStatus.BAD_GATEWAY, e.message ?: "Upstream service unreachable", e)
}

val internalNutrients = handleRetrofitResponse(retrofitResponse)
val publicNutrients = internalNutrients.toPublicNutrients()
return ResponseEntity.ok(publicNutrients)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if the Python nutrient endpoint accepts or uses a language parameter
rg -n -C5 'nutrients' --type py services/py-recipe-service/main.py | head -60

Repository: AET-DevOps26/team-devsecops

Length of output: 1800


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Kotlin controller and models =="
rg -n -C4 'aiNutrientsPost|aiRecipesPost|data class NutrientRequest|data class NutrientRequestForwarded|language' services/spring-api/src/main/kotlin/org/openapitools -g '*.kt'

echo
echo "== OpenAPI / schema references =="
rg -n -C3 'NutrientRequest|NutrientRequestForwarded|language' services/spring-api -g '*.yaml' -g '*.yml' -g '*.kt'

Repository: AET-DevOps26/team-devsecops

Length of output: 50383


Forward NutrientRequest.language to the nutrient service
aiNutrientsPost builds NutrientRequestForwarded with only recipe, so the public language field is dropped before the Python service sees it. If this endpoint should honor the documented active-language context, add language to the forwarded schema and pass it through here; otherwise remove it from NutrientRequest.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/spring-api/src/main/kotlin/org/openapitools/api/AIApiController.kt`
around lines 101 - 121, Preserve NutrientRequest.language when forwarding
requests from aiNutrientsPost: add a corresponding language field to
NutrientRequestForwarded and populate it from nutrientRequest.language when
constructing the internal request. If language is intentionally unsupported,
remove it from the public NutrientRequest model instead.

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