Skip to content

feat: add community feed board UI and mock data integration - #68

Merged
jpdevhub merged 7 commits into
jpdevhub:mainfrom
mithaliphadtare:feat/community-page
Jul 23, 2026
Merged

feat: add community feed board UI and mock data integration#68
jpdevhub merged 7 commits into
jpdevhub:mainfrom
mithaliphadtare:feat/community-page

Conversation

@mithaliphadtare

@mithaliphadtare mithaliphadtare commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Community Question and Answer Board

Related Issue

Closes #25

Changes

Here is a brief summary of the changes:

  1. Fixed Environment Variables: Resolved TypeScript errors by checking for window availability before accessing configuration URLs.
  2. Corrected Function Syntax: Fixed the Community Page function signature from an unclosed ( to a standard React { block.
  3. Balanced JSX Tags: Fixed broken, unclosed HTML layouts inside the array loops that were crashing the file rendering.
  4. Cleaned Event Handlers: Separated inline state assignments into dedicated callback helper functions.
  5. Installed Core Packages: Ran npm install inside the correct subdirectory to restore missing React types and remove 73 core warnings.
  6. also libraries needed to installed mention in requirement.txt

Testing

[x] Tested locally (describe steps)
1.Frontend Isolation: Navigated to the frontend directory, initialized local node modules using npm install to load correct core types, and booted up the decoupled interface server via npm run dev. Verified that the community dashboard mounts perfectly on http://localhost:3000/community with zero remaining syntax or layout errors.

2.Backend & API Mocking: Verified the data-binding layer by isolating communityApi from live database configurations. Successfully tested the page loops, nested comment arrays, and submission state transitions using local mock structural objects to ensure error handling and UI stability without requiring a running backend stack.

Checklist

  • Code follows the project's TypeScript / Python style conventions
  • No secrets or .env values are committed
  • CI passes

#screenshots
added.
mn

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added a Community page with a feed that loads posts with their associated comments.
    • Users can create new community posts (title, content, optional image).
    • Users can add comments to posts and refresh the feed after posting.
  • Bug Fixes

    • Ensured the chatbot reliably returns the fallback response when retry attempts don’t succeed.
  • Maintenance

    • Updated TypeScript type definition versions.
    • Added/updated mypy configuration for smoother type checking.

@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown

@mithaliphadtare is attempting to deploy a commit to the karan3431's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions

Copy link
Copy Markdown

🎉 Thanks for your contribution, @mithaliphadtare!

Please make sure CI passes and the checklist in the PR template is complete. A maintainer will review this soon.

— The AgroNavis team

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jpdevhub, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 46 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2464280e-0593-4f03-a15b-47025a24e704

📥 Commits

Reviewing files that changed from the base of the PR and between 8f176b9 and f1ecb12.

📒 Files selected for processing (3)
  • backend/main.py
  • backend/mypy.ini
  • backend/supabase/migrations/20260620000000_community_feed.sql

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key: "instructions"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
📝 Walkthrough

Walkthrough

Adds a full-stack community Q&A board with authenticated Supabase-backed post and comment endpoints, a frontend API utility, and a React page for feed display and submissions. Also adds an explicit chatbot fallback, mypy configuration, and updated frontend type definitions.

Changes

Community Q&A Board

Layer / File(s) Summary
Backend community endpoints
backend/main.py
Adds request schemas and authenticated endpoints for fetching posts with nested comments and creating posts and comments.
Frontend community API contract
frontend/src/utils/communityApi.ts
Adds post/comment interfaces, Supabase token extraction, and API methods for feed and submissions.
Community page flow
frontend/src/pages/community.tsx
Adds feed loading, post/comment forms, submission handlers, refresh behavior, and post rendering.

Backend reliability and typing

Layer / File(s) Summary
Chatbot retry fallback
backend/chatbot.py
Returns the rule-based fallback after unsuccessful Gemini retries.
Backend mypy configuration
backend/mypy.ini
Adds missing-import handling and selected disabled error codes.

Frontend type definitions

Layer / File(s) Summary
Type definition updates
frontend/package.json
Updates @types/node and @types/react development dependency versions.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant communityApi
  participant FastAPI
  participant Supabase

  Browser->>communityApi: getFeed()
  communityApi->>FastAPI: GET /api/community/posts
  FastAPI->>Supabase: select posts and comments
  Supabase-->>FastAPI: ordered rows
  FastAPI-->>communityApi: posts with nested comments
  communityApi-->>Browser: render feed

  Browser->>communityApi: createPost() or createComment()
  communityApi->>FastAPI: authenticated POST request
  FastAPI->>Supabase: insert record with user_id
  Supabase-->>FastAPI: inserted row
  FastAPI-->>communityApi: created record
  Browser->>communityApi: getFeed()
Loading

Possibly related PRs

Suggested labels: Hard, backend

Suggested reviewers: jpdevhub

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning backend/chatbot.py and mypy.ini changes are unrelated to the community board scope. Remove unrelated chatbot and config edits, or explain why they are required for issue #25.
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 matches the new community board UI and API work.
Linked Issues check ✅ Passed The PR adds a Supabase-backed community board with posts, comments, and image sharing, satisfying issue #25.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@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: 6

🤖 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 `@backend/main.py`:
- Around line 864-865: The exception handlers in the code are exposing raw error
details to API clients by using str(e) directly in the HTTPException detail,
which creates a security vulnerability. Replace all instances where raw
exception strings are returned (in the except Exception as e blocks at lines
864-865, 880-881, and 895-896) with a generic message like "An error occurred"
or "Internal server error", and instead log the actual exception details using a
server-side logger so debugging information is available in logs but not exposed
to clients.
- Around line 852-862: The current implementation has O(posts × comments)
complexity because the nesting loop iterates through all_comments for every post
using a list comprehension. Build a dictionary index first that maps post_id to
a list of comments, then iterate through posts and assign comments using the
index. Specifically, after fetching all_comments, create a dictionary where keys
are post_id values and values are lists of comments belonging to that post, then
in the for loop that processes posts, assign post["comments"] by looking up the
post["id"] in the index dictionary instead of filtering through all_comments
each time.

In `@frontend/src/pages/community.tsx`:
- Line 40: The fetchFeed() function calls at lines 40 and 53 are not being
awaited, which means any errors during feed refresh will not be caught by the
surrounding try/catch blocks and can result in unhandled promise rejections. Add
the await keyword before both fetchFeed() calls to ensure they complete and any
errors are properly caught by the try/catch blocks that wrap these operations.
- Around line 107-109: The empty-state message in the conditional rendering
block is displaying even when an error exists, causing both error and
empty-state messages to appear simultaneously. Add an !error check to the
existing condition that currently checks !loading && posts.length === 0 so that
the empty-state message only renders when there is no error present, ensuring a
consistent and non-conflicting state representation.

In `@frontend/src/utils/communityApi.ts`:
- Around line 17-20: The JSON.parse call when parsing the localStorage value in
communityApi.ts can throw an exception if the stored data is malformed or stale,
causing all API calls to fail. Wrap the entire localStorage retrieval and
JSON.parse logic in a try/catch block, and when an error is caught or the
parsing fails, fall back to using unauthenticated headers instead of breaking
the API call flow. This ensures the function continues to work even when the
cached session data is invalid.
- Around line 2-3: Replace the invalid window.process pattern with direct access
to the Next.js environment variable. Remove the globalEnv variable and the
window check, then change the BASE_URL assignment to use
process.env.NEXT_PUBLIC_API_BASE_URL directly (note the correct name is
NEXT_PUBLIC_API_BASE_URL, not NEXT_PUBLIC_API_URL as currently referenced). Keep
the fallback to 'http://localhost:8000' if the environment variable is
undefined. This aligns with the idiomatic Next.js pattern used in farmApi.ts and
supabase.ts where NEXT_PUBLIC_ prefixed variables are safely accessed directly
in client code.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a42be421-d478-4b51-8c1d-cce935e66c7f

📥 Commits

Reviewing files that changed from the base of the PR and between e220859 and aafc090.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • backend/main.py
  • backend/supabase/migrations/20260620000000_community_feed.sql
  • frontend/package.json
  • frontend/src/pages/community.tsx
  • frontend/src/utils/communityApi.ts

Comment thread backend/main.py
Comment thread backend/main.py Outdated
Comment thread frontend/src/pages/community.tsx Outdated
Comment thread frontend/src/pages/community.tsx Outdated
Comment thread frontend/src/utils/communityApi.ts Outdated
Comment thread frontend/src/utils/communityApi.ts

@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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
backend/main.py (2)

834-834: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Do not expose raw exception details to API clients.

The detail=str(e) directly returns backend error messages to clients, potentially exposing database errors, file paths, or system details. Return a generic message and log the actual error server-side instead.

🔒 Proposed fix to sanitize exception exposure
     except Exception as e:
-        raise HTTPException(status_code=500, detail=str(e))
+        print(f"Error in wiki search: {str(e)}")
+        raise HTTPException(
+            status_code=500,
+            detail="An internal server error occurred while processing the wiki search."
+        ) from e
🤖 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 `@backend/main.py` at line 834, The HTTPException being raised with
detail=str(e) exposes raw backend error information to API clients, creating a
security risk. Replace the detail parameter with a generic error message like
"An internal server error occurred" and instead log the actual exception details
(the variable e) using a server-side logger at the error level. This ensures
sensitive system information is only visible in server logs, not exposed to
clients.

78-95: ⚠️ Potential issue | 🟠 Major

Apply consistent exception handling to match the sanitization pattern in community endpoints.

The new community endpoints correctly use generic error messages (e.g., "An internal server error occurred while processing the community feed."), but the verify_token function and other endpoints still expose raw exception details. Update line 95 and the similar patterns at lines 531, 779, and 834 to sanitize error messages consistently across all endpoints.

🤖 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 `@backend/main.py` around lines 78 - 95, The verify_token function currently
exposes raw exception details in the error message (line 95) by including str(e)
in the HTTPException detail, which is inconsistent with the sanitization pattern
used in the community endpoints. Replace the dynamic error message in the
verify_token function that includes str(e) with a generic error message like "An
internal server error occurred" to avoid exposing implementation details. Apply
the same sanitization pattern to the similar error handling blocks at lines 531,
779, and 834 by removing exception details from all HTTPException detail
messages and using consistent generic error messages instead.
🧹 Nitpick comments (1)
backend/main.py (1)

877-880: ⚡ Quick win

Add exception chaining for better debugging.

Python best practice (PEP 3134) recommends using from e to preserve the exception chain, which helps with debugging while still controlling the client-facing message.

♻️ Proposed fix to add exception chaining
         raise HTTPException(
             status_code=500, 
             detail="An internal server error occurred while processing the community feed."
-        )
+        ) from e
🤖 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 `@backend/main.py` around lines 877 - 880, The HTTPException being raised in
the community feed error handler is not preserving the original exception chain.
Modify the raise HTTPException statement to include exception chaining by adding
`from e` at the end of the raise statement, where `e` is the caught exception
variable. This will ensure the original exception context is preserved for
debugging while still returning the generic error message to the client.
🤖 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 `@backend/main.py`:
- Around line 896-901: The error log message in the exception handling block
says "Error fetching community feed" but this code is located in the
`create_community_post` endpoint, which is misleading for debugging post
creation failures. Update the print statement message to accurately reflect that
an error occurred while creating a community post instead of fetching a feed,
and modify the raise HTTPException statement to use exception chaining with
`from e` syntax to preserve the original exception context.
- Around line 916-921: The error log message in the exception handler for the
create_community_comment endpoint incorrectly states "Error fetching community
feed" which appears to be copy-pasted from another endpoint. Update the print
statement to accurately reflect the actual operation being performed (creating a
community comment rather than fetching a feed). Additionally, add exception
chaining by using the from e syntax in the raise statement to preserve the
original error context for debugging purposes.

---

Outside diff comments:
In `@backend/main.py`:
- Line 834: The HTTPException being raised with detail=str(e) exposes raw
backend error information to API clients, creating a security risk. Replace the
detail parameter with a generic error message like "An internal server error
occurred" and instead log the actual exception details (the variable e) using a
server-side logger at the error level. This ensures sensitive system information
is only visible in server logs, not exposed to clients.
- Around line 78-95: The verify_token function currently exposes raw exception
details in the error message (line 95) by including str(e) in the HTTPException
detail, which is inconsistent with the sanitization pattern used in the
community endpoints. Replace the dynamic error message in the verify_token
function that includes str(e) with a generic error message like "An internal
server error occurred" to avoid exposing implementation details. Apply the same
sanitization pattern to the similar error handling blocks at lines 531, 779, and
834 by removing exception details from all HTTPException detail messages and
using consistent generic error messages instead.

---

Nitpick comments:
In `@backend/main.py`:
- Around line 877-880: The HTTPException being raised in the community feed
error handler is not preserving the original exception chain. Modify the raise
HTTPException statement to include exception chaining by adding `from e` at the
end of the raise statement, where `e` is the caught exception variable. This
will ensure the original exception context is preserved for debugging while
still returning the generic error message to the client.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ded54e32-9a48-4526-83e8-dc49312590ea

📥 Commits

Reviewing files that changed from the base of the PR and between aafc090 and 6ad0390.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • backend/main.py
  • frontend/src/pages/community.tsx
  • frontend/src/utils/communityApi.ts
  • requirements.txt
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/pages/community.tsx
  • frontend/src/utils/communityApi.ts

Comment thread backend/main.py
Comment thread backend/main.py
@jpdevhub

Copy link
Copy Markdown
Owner

Hey, it looks like there are merge conflicts with the main branch because we recently merged some other PRs! Could you please pull the latest main into your branch, resolve the conflicts in backend/main.py and package-lock.json, and push again?

@mithaliphadtare

Copy link
Copy Markdown
Contributor Author

@jpdevhub pls check I update pr

@jpdevhub

Copy link
Copy Markdown
Owner

Hey! It looks like you tried to manually resolve the merge conflict inside frontend/package-lock.json. Unfortunately, because it's a massive generated file, doing this left some stray text (feat/community-page and main) inside the file, making it invalid JSON. Because it's invalid JSON, the testing framework is crashing entirely!

The easiest way to resolve a package-lock.json conflict is to just regenerate it: 1. cd frontend 2. rm package-lock.json (Delete the corrupted file) 3. npm install (This will cleanly generate a brand new lockfile without conflicts) 4. Commit the new lockfile and push!

@jpdevhub jpdevhub left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks for contributing

@vercel

vercel Bot commented Jul 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agronavis-ai-farm-assiatant Ready Ready Preview, Comment Jul 23, 2026 10:19am

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (12)
backend/main.py (8)

1049-1054: 🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift

Bound community feed reads.

Every request loads every post and every comment. The indexing fix removes the quadratic nesting cost, but I/O and memory usage remain unbounded as the board grows. Add cursor/limit pagination and fetch comments only for the returned post IDs.

🤖 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 `@backend/main.py` around lines 1049 - 1054, Update the community feed read
flow around the posts and comments queries to paginate posts with a cursor and
fixed limit, then fetch comments only for the returned post IDs rather than
loading the entire comments table. Preserve the existing ordering and
empty-result handling while applying the same bounded approach to comments.

1087-1088: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not return 201 with null or incomplete resources.

Both creation endpoints silently return data: null when Supabase returns no rows. Additionally, the created post lacks the required comments array expected by frontend/src/utils/communityApi.ts Lines 63-84. Fail when no row is returned and return a feed-shaped post with comments: [].

         res = supabase.table("posts").insert(payload).execute()
-        return {"success": True, "data": (res.data[0] if res.data else None)}
+        if not res.data:
+            raise HTTPException(status_code=500, detail="Failed to create post")
+        return {"success": True, "data": {**res.data[0], "comments": []}}

Also applies to: 1107-1108

🤖 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 `@backend/main.py` around lines 1087 - 1088, Update both post creation
endpoints around the Supabase insert execution to fail instead of returning
success when res.data is empty, avoiding a 201 response with null data. When a
row exists, return the created post in the feed shape expected by communityApi,
ensuring it includes comments initialized to an empty array while preserving the
existing response structure.

1102-1106: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Return 404 when the target post is missing.

public.comments.post_id already references public.posts(id), so invalid IDs fail at the database constraint. In create_community_comment, catch that constraint error and return a client-facing 404 before falling back to the generic 500 handler for other failures.

🤖 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 `@backend/main.py` around lines 1102 - 1106, Update create_community_comment
around the payload insertion to catch the database foreign-key constraint error
caused by a missing post and return a client-facing 404 response; preserve the
existing generic 500 handling for all other failures.

913-913: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve explicit zero organic matter.

soil.organic_matter or 1.5 treats a valid 0.0 value as missing and assigns it a nonzero default. Check for None explicitly.

-    om_score = min((soil.organic_matter or 1.5) / 3.0, 1.0)
+    om_score = min(
+        (soil.organic_matter if soil.organic_matter is not None else 1.5) / 3.0,
+        1.0,
+    )
🤖 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 `@backend/main.py` at line 913, Update the organic matter calculation around
om_score to use the 1.5 default only when soil.organic_matter is None,
preserving an explicit 0.0 value before applying the normalization and cap.

935-946: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Read yield area from farm_fields.

The field endpoints write to farm_fields at Lines 680-685 and 718, but this code reads the obsolete farms.location.fields. Newly drawn fields are therefore ignored and prediction falls back to total_area.

-    location = farm.get("location") or {}
-    fields: list = location.get("fields", [])
+    fields_response = (
+        supabase.table("farm_fields")
+        .select("polygon")
+        .eq("farm_id", farm_id)
+        .execute()
+    )
+    fields = fields_response.data or []
🤖 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 `@backend/main.py` around lines 935 - 946, Update the area calculation in the
prediction flow around _compute_polygon_area_hectares to read field records from
the farm_fields data source used by the field endpoints, rather than
farm.location.fields. Sum the polygon areas from those records and retain the
total_area fallback only when no farm_fields records are available.

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

Use the actual user type for authenticated dependencies.

verify_token resolves to auth.get_user(...).user, not a generic dict, and the handlers read user.id. Use User / AuthResponse.user or an Annotated protocol consistently, including line 925, so the annotations match runtime behavior.

🤖 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 `@backend/main.py` at line 665, Update the authenticated dependency annotations
in the handlers around the dependency using verify_token, including the
corresponding dependency near line 925, to use the actual user type returned by
auth.get_user(...).user rather than dict. Reuse the existing
User/AuthResponse.user type or established Annotated protocol consistently,
while preserving the handlers’ user.id access.

253-258: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject invalid soil measurements before prediction.

Negative nitrogen, phosphorus, potassium, or organic-matter values are accepted and can push _soil_modifier() below its documented 0.5 lower bound, producing lower or negative predicted yields. Add non-negative schema constraints for these metrics and constrain ph to a valid soil pH range.

🤖 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 `@backend/main.py` around lines 253 - 258, Update the SoilHealthInput model to
validate nitrogen, phosphorus, potassium, and optional organic_matter as
non-negative values, and constrain ph to the supported valid soil pH range
before prediction. Use the model’s schema validation mechanisms so invalid
measurements are rejected before _soil_modifier() and prediction logic run.

125-132: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Use explicit safe checkpoint deserialization.

backend/model/plant_disease_resnet18.pth is an external model weight artifact and is loaded with pickle-based torch.load(). Load the state dict with weights_only=True so the load path cannot execute arbitrary code if the artifact is replaced or untrusted.

🤖 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 `@backend/main.py` around lines 125 - 132, Update the checkpoint loading call
in the ResNet18 initialization block to pass weights_only=True to torch.load,
while preserving the existing map_location=device behavior and subsequent
load_state_dict flow.

Source: Linters/SAST tools

backend/chatbot.py (4)

128-129: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not expose raw exception details to clients.

detail=str(exc) can leak internal paths, parser errors, or upstream response details. Log the exception server-side, return a generic message, and use raise ... from exc when preserving the cause.

🤖 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 `@backend/chatbot.py` around lines 128 - 129, Update the exception handler
around the HTTPException construction to log the caught exception server-side,
replace detail=str(exc) with a generic client-safe message, and raise the
HTTPException from exc to preserve the original cause.

Source: Linters/SAST tools


13-18: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Validate conversation history entries before indexing them.

history: list[dict] accepts items without content or with non-string values; Line [65] then raises KeyError and returns 500 instead of a validation error. Use a Pydantic history model with a constrained role and required content.

Also applies to: 53-53, 61-65

🤖 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 `@backend/chatbot.py` around lines 13 - 18, Update ChatRequest.history to use a
dedicated Pydantic history-entry model instead of list[dict], requiring a string
content field and constraining role to the supported role values. Ensure the
chatbot handling around the history processing at lines 53 and 61-65 consumes
the validated model fields without direct indexing that can raise KeyError, so
malformed entries produce validation errors.

78-90: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Handle Gemini transport errors and fallback on missing candidates.

client.post() exceptions are not caught inside _call_gemini, and the 200 path unconditionally indexes candidates[0].content.parts[0].text; missing candidates/keys or malformed JSON escape to chat(), which returns a 500 instead of falling back. Catch transport/JSON errors and validate the response shape before returning the extracted text.

🤖 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 `@backend/chatbot.py` around lines 78 - 90, Update _call_gemini to catch httpx
transport exceptions and JSON parsing or response-shape errors from client.post
and the 200 response path, returning _fallback_response(message) instead of
propagating failures. Validate candidates, content, parts, and text exist and
are usable before extracting the response; preserve the existing retry behavior
for HTTP 503 responses.

75-75: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Send the Gemini API key in the x-goog-api-key header.

Remove ?key=... from the URL and pass the key in the request headers:

url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent"
resp = await client.post(url, json=payload, headers={"x-goog-api-key": api_key})

Putting the secret in the query string can expose it in URL/proxy/server logs.

🤖 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 `@backend/chatbot.py` at line 75, Update the Gemini request URL construction in
the chatbot request flow to remove the api_key query parameter, and pass the key
through the request headers using x-goog-api-key when calling the HTTP client's
post method. Preserve the existing payload and request behavior.
🤖 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 `@backend/mypy.ini`:
- Around line 2-3: Reduce the global suppressions configured in mypy.ini: remove
broad codes such as assignment, return-value, attr-defined, and index from the
backend-wide disable_error_code setting, then scope any necessary exceptions to
the specific affected modules or lines. Keep only narrowly justified
suppressions so normal mypy type checks remain active across chatbot and image
model code.

---

Outside diff comments:
In `@backend/chatbot.py`:
- Around line 128-129: Update the exception handler around the HTTPException
construction to log the caught exception server-side, replace detail=str(exc)
with a generic client-safe message, and raise the HTTPException from exc to
preserve the original cause.
- Around line 13-18: Update ChatRequest.history to use a dedicated Pydantic
history-entry model instead of list[dict], requiring a string content field and
constraining role to the supported role values. Ensure the chatbot handling
around the history processing at lines 53 and 61-65 consumes the validated model
fields without direct indexing that can raise KeyError, so malformed entries
produce validation errors.
- Around line 78-90: Update _call_gemini to catch httpx transport exceptions and
JSON parsing or response-shape errors from client.post and the 200 response
path, returning _fallback_response(message) instead of propagating failures.
Validate candidates, content, parts, and text exist and are usable before
extracting the response; preserve the existing retry behavior for HTTP 503
responses.
- Line 75: Update the Gemini request URL construction in the chatbot request
flow to remove the api_key query parameter, and pass the key through the request
headers using x-goog-api-key when calling the HTTP client's post method.
Preserve the existing payload and request behavior.

In `@backend/main.py`:
- Around line 1049-1054: Update the community feed read flow around the posts
and comments queries to paginate posts with a cursor and fixed limit, then fetch
comments only for the returned post IDs rather than loading the entire comments
table. Preserve the existing ordering and empty-result handling while applying
the same bounded approach to comments.
- Around line 1087-1088: Update both post creation endpoints around the Supabase
insert execution to fail instead of returning success when res.data is empty,
avoiding a 201 response with null data. When a row exists, return the created
post in the feed shape expected by communityApi, ensuring it includes comments
initialized to an empty array while preserving the existing response structure.
- Around line 1102-1106: Update create_community_comment around the payload
insertion to catch the database foreign-key constraint error caused by a missing
post and return a client-facing 404 response; preserve the existing generic 500
handling for all other failures.
- Line 913: Update the organic matter calculation around om_score to use the 1.5
default only when soil.organic_matter is None, preserving an explicit 0.0 value
before applying the normalization and cap.
- Around line 935-946: Update the area calculation in the prediction flow around
_compute_polygon_area_hectares to read field records from the farm_fields data
source used by the field endpoints, rather than farm.location.fields. Sum the
polygon areas from those records and retain the total_area fallback only when no
farm_fields records are available.
- Line 665: Update the authenticated dependency annotations in the handlers
around the dependency using verify_token, including the corresponding dependency
near line 925, to use the actual user type returned by auth.get_user(...).user
rather than dict. Reuse the existing User/AuthResponse.user type or established
Annotated protocol consistently, while preserving the handlers’ user.id access.
- Around line 253-258: Update the SoilHealthInput model to validate nitrogen,
phosphorus, potassium, and optional organic_matter as non-negative values, and
constrain ph to the supported valid soil pH range before prediction. Use the
model’s schema validation mechanisms so invalid measurements are rejected before
_soil_modifier() and prediction logic run.
- Around line 125-132: Update the checkpoint loading call in the ResNet18
initialization block to pass weights_only=True to torch.load, while preserving
the existing map_location=device behavior and subsequent load_state_dict flow.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bc0a9f20-11e3-437e-ae25-9cf6435027de

📥 Commits

Reviewing files that changed from the base of the PR and between 4e12d9c and 8f176b9.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • backend/chatbot.py
  • backend/main.py
  • backend/mypy.ini
  • frontend/package.json

Comment thread backend/mypy.ini Outdated
@jpdevhub
jpdevhub merged commit 5346af7 into jpdevhub:main Jul 23, 2026
7 checks passed
@github-actions

Copy link
Copy Markdown

🎉 Awesome work! Your PR has been successfully merged.

Thank you for your contribution! If you find this project interesting, please don't forget to star ⭐️ the repository!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Full-Stack] Community Q&A Board

2 participants