Skip to content

Harden StudentHubHelp chatbot reliability and controls - #20

Open
StudentHubHelp wants to merge 95 commits into
mainfrom
fix/chatbot-reliability-security
Open

StudentHubHelp wants to merge 95 commits into
mainfrom
fix/chatbot-reliability-security

Conversation

@StudentHubHelp

@StudentHubHelp StudentHubHelp commented Nov 8, 2026 •

Copy link
Copy Markdown
Owner

User description

Scope

Hardens the existing StudentHubHelp chatbot on the isolated branch fix/chatbot-reliability-security. Website pages, Add Listing flow, and unrelated admin/property workflows are not changed. The Edge Function is not deployed and this PR is not merged.

Implemented

  • Runtime config remains fail-closed if the admin config row is missing or unavailable.
  • Distributed atomic rate limiting uses the private private.chatbot_rate_limits table and a restricted service_role-only RPC. The migration was applied to Supabase production and verified: anon/authenticated cannot execute the RPC; service_role can. A concurrent smoke test with 8 requests and a limit of 2 allowed exactly 2 and blocked 6.
  • Missing cf-connecting-ip no longer causes every normal user to receive 503. The fallback uses a low-limit, explicitly untrusted x-forwarded-for key plus session/user-agent keys. This is weaker than a verified Cloudflare IP and must still be checked after Edge Function deployment.
  • Database REST reads, writes, and rate-limit RPC calls have 4-second abort timeouts.
  • Explicit budget filters remain independent of the planner toggle. A combined Hostel + Tiffin monthly-budget optimizer now reads the actual hostels and tiffins tables, respects city/gender and known monthly prices, and returns a bundle budget plan only when the admin planner toggle is enabled.
  • Search uses database-side city, locality, budget, and gender predicates plus primary-key keyset pagination (250 rows/page, 5,000-row safety cap/category).
  • Hindi/Hinglish normalization and deterministic city parsing include Jhunjhunu and Udaipurwati.
  • Nearby search requests device GPS only for generic “near me” queries; without coordinates it asks for a landmark/area instead of inventing distance. React, root widget.js, and bundled ai-chatbot/public/widget.js pass optional GPS coordinates and gracefully handle permission/API errors.
  • React voice input uses hi-IN; unsupported browsers show a typed-input fallback instead of crashing.
  • Production React API URL is pinned to the Supabase Edge Function in .env.production and enforced in production builds; the embed-code generator now emits the same Edge Function URL.
  • Legacy Express server is explicitly local-preview-only, excluded from the clean Vite production build, and available separately as npm run dev:legacy-server; npm start serves only the static Vite preview.
  • Admin save verifies the updated row. Legacy admin/property flows remain unchanged.
  • Added a live regression script covering Sikar/Allen boys hostel, Kota/Talwandi tiffin, Jhunjhunu cafe, Piprali budget, and missing-GPS nearby prompt.

Dependency remediation

  • Root cause identified by npm audit: vulnerable transitive body-parser, proxy-addr, qs, source-map-js, and direct Vite 6.4.3.
  • Added semver-safe overrides and moved Vite to the patched 6.4 line. The CI runs targeted npm update (no --force), persists the updated lockfile, then runs npm audit.
  • Latest completed audit job reported zero vulnerabilities. Patched lockfile versions include body-parser 1.20.9, proxy-addr 2.0.8, qs 6.17.1, source-map-js 1.2.2, and Vite 6.4.5.

Validation

  • Latest completed run #127: Edge Function Deno type-check PASS; React ChatWidget type-check PASS; React production build PASS; npm audit PASS (zero vulnerabilities); regression script and public widget syntax PASS.
  • Private RPC smoke test and concurrent rate-limit test PASS.
  • Live end-to-end prompt suite has not been run because no staging Edge Function endpoint/credentials are configured for this PR. The regression script (including Kota ₹15,000 hostel+tiffin combo and no-GPS fallback) is ready for a local/staging endpoint.
  • Current production data quality limits budget coverage: only 5 of 207 active hostels and 25 of 96 active tiffins have a positive monthly price; Sikar currently has no active hostel with a positive monthly price. The planner intentionally returns no fabricated combo where monthly prices are missing. Kota currently has priced hostel+tiffin pairs within the ₹15,000 test budget.
  • Cloudflare trusted IP header availability, browser GPS permissions, Safari/Android voice behavior, and full chatbot search results still require staging/device verification.

Production / rollout

  • Supabase production migration 20261108164241_chatbot_distributed_rate_limit has been applied and smoke-tested.
  • Edge Function code, React widget, and public widget.js have not been deployed to production.
  • No PR merge or live website deployment has occurred.
  • Next gate: deploy this branch to a staging Edge Function, run ai-chatbot/tests/chatbot-regression.mjs with CHATBOT_TEST_URL and SUPABASE_ANON_KEY, verify cf-connecting-ip, then approve production Edge Function deployment.

CodeAnt-AI Description

Make chatbot recommendations more accurate and easier to recover when requests fail

What Changed

  • Live searches now filter active listings by city, category, area, gender, and budget, and can build a hostel-and-tiffin plan from listed monthly prices.
  • For generic nearby searches, the chatbot requests device location when available and shows a verified distance or a clear area match; without location, it asks for a landmark or area.
  • Users can retry after temporary service failures without retyping, and browsers without voice input support receive a typed-input prompt.
  • Admin controls now govern the live chatbot, and saving settings confirms the change was recorded.

Impact

✅ Fewer out-of-city and over-budget recommendations
✅ Nearby results with clearer distance evidence
✅ Retry temporary chat failures without retyping

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@StudentHubHelp
StudentHubHelp marked this pull request as ready for review November 9, 2026 03:12
@codeant-ai

codeant-ai Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

CodeAnt  CodeAnt Review Status

✅  Review completed

Status Commit Started (UTC) Finished (UTC)
✅  #b4634 Reviewed your PR 1a511c0 Nov 09, 2026 · 03:12 03:22

@codeant-ai

codeant-ai Bot commented Nov 9, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added the size:XL This PR changes 500-999 lines, ignoring generated files label Nov 9, 2026
Comment on lines +21 to +22
permissions:
contents: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: This grants write access to the token in pull-request runs while npm install executes PR-controlled lifecycle scripts, letting those scripts push arbitrary commits to the repository.

Assessment: 🔴 Critical · 🔁 Occurrence: Rarely · 🏷️ Security

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** .github/workflows/chatbot-pr-check.yml
**Line:** 21:22
**Comment:**
	*Security: This grants write access to the token in pull-request runs while `npm install` executes PR-controlled lifecycle scripts, letting those scripts push arbitrary commits to the repository.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

git add package-lock.json
if ! git diff --cached --quiet; then
git commit -m "chore(chatbot): patch audited dependencies [skip ci]"
git push origin "HEAD:$TARGET_BRANCH"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: push and pull_request both run for this branch; if npm update changes the lockfile, both workflows push from the same parent, so one push is rejected and its check fails.

Assessment: 🟠 Major · 🔁 Occurrence: Rarely · 🏷️ Race condition

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** .github/workflows/chatbot-pr-check.yml
**Line:** 64:64
**Comment:**
	*Race Condition: `push` and `pull_request` both run for this branch; if `npm update` changes the lockfile, both workflows push from the same parent, so one push is rejected and its check fails.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

onClick={() => {
if (onSendQuery) {
onSendQuery(`Mera monthly budget ₹${sliderBudget} hai, isme best verified hostel aur tiffin combo suggest karo`);
onSendQuery(`Mera monthly budget ₹${sliderBudget} hai, ${initialPlan.city ? initialPlan.city + " mein " : ""}best verified hostel aur tiffin combo suggest karo`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: This request asks for verified listings, but the combo search selects active, priced rows without filtering verified, so unverified options can be returned.

Assessment: 🟠 Major · 🔁 Occurrence: Sometimes · 🏷️ Api mismatch

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** ai-chatbot/src/components/BudgetPlannerCard.tsx
**Line:** 288:288
**Comment:**
	*Api Mismatch: This request asks for verified listings, but the combo search selects active, priced rows without filtering `verified`, so unverified options can be returned.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

if (!SUPABASE_ANON_KEY) throw new Error('Missing VITE_SUPABASE_ANON_KEY. Add the public Supabase anon/publishable key to the Vite build environment.');
const controller = new AbortController(); const timeoutId = window.setTimeout(() => controller.abort(), 20000); let res: Response;
const clientCoords = asksForNearbyLocation(text) ? await getUserDeviceLocation() : null;
const controller = new AbortController(); const timeoutId = window.setTimeout(() => controller.abort(), 15000); let res: 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.

Suggestion: The abort timer is cleared once response headers arrive, before res.json() consumes the body; a stalled body leaves loading stuck with no retry.

Assessment: 🟠 Major · 🔁 Occurrence: Rarely · 🏷️ Possible bug

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** ai-chatbot/src/components/ChatWidget.tsx
**Line:** 152:152
**Comment:**
	*Possible Bug: The abort timer is cleared once response headers arrive, before `res.json()` consumes the body; a stalled body leaves loading stuck with no retry.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment on lines +63 to +64
const hostelCap=Math.floor(totalBudget*0.70),tiffinCap=Math.floor(totalBudget*0.35);
const [hostelRows,tiffinRows]=await Promise.all([direct("hostel",cityName,hostelCap,undefined,genderFilter),direct("tiffin",cityName,tiffinCap)]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The per-category caps discard valid pairs before checking the total: a hostel costing 75% and tiffin costing 20% fits the budget but is excluded by the 70% hostel cap.

Assessment: 🟠 Major · 🔁 Occurrence: Sometimes · 🏷️ Logic error

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** supabase/functions/studenthubhelp-chat/index.ts
**Line:** 63:64
**Comment:**
	*Logic Error: The per-category caps discard valid pairs before checking the total: a hostel costing 75% and tiffin costing 20% fits the budget but is excluded by the 70% hostel cap.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

const pricedHostels=hostels.map(p=>({p,cost:monthlyAmount(p,"hostel")})).filter(x=>x.cost!==undefined) as Array<{p:any;cost:number}>;
const pricedTiffins=tiffins.map(p=>({p,cost:monthlyAmount(p,"tiffin")})).filter(x=>x.cost!==undefined) as Array<{p:any;cost:number}>;
let best:{hostel:any;tiffin:any;hostelCost:number;tiffinCost:number;total:number;score:number}|undefined;
for(const h of pricedHostels)for(const t of pricedTiffins){const total=h.cost+t.cost;if(total>totalBudget)continue;const score=Math.abs(h.cost-totalBudget*0.65)+Math.abs(t.cost-totalBudget*0.35)+(totalBudget-total)*0.15;if(!best||score<best.score)best={hostel:h.p,tiffin:t.p,hostelCost:h.cost,tiffinCost:t.cost,total,score}}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The UI requests a “verified” combo, but this selection scores all active priced rows without checking verified, so an unverified hostel or tiffin can be returned.

Assessment: 🟠 Major · 🔁 Occurrence: Sometimes · 🏷️ Incorrect condition logic

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** supabase/functions/studenthubhelp-chat/index.ts
**Line:** 69:69
**Comment:**
	*Incorrect Condition Logic: The UI requests a “verified” combo, but this selection scores all active priced rows without checking `verified`, so an unverified hostel or tiffin can be returned.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

for(const h of pricedHostels)for(const t of pricedTiffins){const total=h.cost+t.cost;if(total>totalBudget)continue;const score=Math.abs(h.cost-totalBudget*0.65)+Math.abs(t.cost-totalBudget*0.35)+(totalBudget-total)*0.15;if(!best||score<best.score)best={hostel:h.p,tiffin:t.p,hostelCost:h.cost,tiffinCost:t.cost,total,score}}
return best;
}
function genderWanted(s:string){const x=n(normalizeSearchTerms(s));if(/\b(girls|girl|female|ladki|ladkiyo|ladkiyon|महिला|लड़क|लड़की|girls hostel)\b/i.test(x))return "girls";if(/\b(boys|boy|male|ladke|ladkon|लड़के|लड़का|boys hostel)\b/i.test(x))return "boys";return ""}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: \\b uses ASCII word boundaries, so Devanagari alternatives such as महिला and लड़के do not match; offline searches can omit the requested gender filter and show the wrong listings.

Assessment: 🟠 Major · 🔁 Occurrence: Sometimes · 🏷️ Incorrect condition logic

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** supabase/functions/studenthubhelp-chat/index.ts
**Line:** 72:72
**Comment:**
	*Incorrect Condition Logic: `\\b` uses ASCII word boundaries, so Devanagari alternatives such as `महिला` and `लड़के` do not match; offline searches can omit the requested gender filter and show the wrong listings.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

return "Main bina external AI API key ke live StudentHubHelp listings, location-based search, booking guidance aur kuch common study/general questions handle kar sakta hoon. Is sawaal ka reliable jawab dene ke liye thoda aur context ya specific question bhej dijiye 😊";
}
async function aiGeneral(msg:string,history:any[]){const offline=offlineGeneralReply(msg);if(!GEMINI||offline!=="Main bina external AI API key ke live StudentHubHelp listings, location-based search, booking guidance aur kuch common study/general questions handle kar sakta hoon. Is sawaal ka reliable jawab dene ke liye thoda aur context ya specific question bhej dijiye 😊")return{reply:offline,webGrounded:false,webSources:[]};try{const h=history.slice(-8).map(x=>({role:x.role==="assistant"?"model":"user",parts:[{text:String(x.text||"").slice(0,1500)}]}));const system=`You are StudentHubHelp's Ultra Advance AI Assistant for students.
async function aiGeneral(msg:string,history:any[],cfg:ChatbotRuntimeConfig=DEFAULT_RUNTIME_CONFIG,deadlineAt?:number){const offline=offlineGeneralReply(msg);if(!GEMINI||offline!=="Main bina external AI API key ke live StudentHubHelp listings, location-based search, booking guidance aur kuch common study/general questions handle kar sakta hoon. Is sawaal ka reliable jawab dene ke liye thoda aur context ya specific question bhej dijiye 😊")return{reply:offline,webGrounded:false,webSources:[]};try{const h=history.slice(-8).map(x=>({role:x.role==="assistant"?"model":"user",parts:[{text:String(x.text||"").slice(0,1500)}]}));const system=`You are StudentHubHelp's Ultra Advance AI Assistant for students.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: React sends assistant history with role model, but this mapper treats every non-assistant role as user; Gemini then receives prior assistant text as user statements.

Assessment: 🟠 Major · 🔁 Occurrence: Sometimes · 🏷️ Api mismatch

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** supabase/functions/studenthubhelp-chat/index.ts
**Line:** 282:282
**Comment:**
	*Api Mismatch: React sends assistant history with role `model`, but this mapper treats every non-`assistant` role as `user`; Gemini then receives prior assistant text as user statements.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

const previous=history.filter(x=>x.role==="user").map(x=>x.text||"").join(" "),combined=previous+" "+msg,aiRaw=await aiUnderstand(msg,history),u=mergeIntent(aiRaw,msg,history),explicitCat=cat(msg),nearCats=secondaryCats(msg),aiCats=u.categories||[],c=u.category||explicitCat||(u.followUp?cat(previous):""),propertyMode=u.intent.startsWith("property_")||isPropertyQuery(msg,u.followUp?previous:""),ct=u.city||(u.followUp?city(previous):""),near=u.landmark||u.area||u.locality||(u.nearRelation?nearTerm(msg):""),locationForFilter=strictLocation(msg),action=String(b?.action||u.action||""),shownList=(Array.isArray(b?.shownPropertyIds)?b.shownPropertyIds:[]).map((x:any)=>String(x)),shownIds=new Set(shownList);
const previous=history.filter(x=>x.role==="user").map(x=>x.text||"").join(" "),combined=previous+" "+msg,aiRaw=await aiUnderstand(msg,history,cfg,requestDeadlineAt),u=mergeIntent(aiRaw,msg,history),explicitCat=cat(msg),nearCats=secondaryCats(msg),multiCategoryRequest=/(?:\b(?:and|plus|with)\b|\+|\baur\b|और)/i.test(n(msg)),detectedCats=["hostel","tiffin","library","cafe","bookstore"].filter(type=>new RegExp(type==="hostel"?"hostel|\\bpg\\b|हॉस्टल|पीजी":type==="tiffin"?"tiffin|mess|meal|टिफिन|मेस":type==="library"?"library|reading room|लाइब्रेरी":type==="cafe"?"cafe|कैफे":"bookstore|book shop|stationery|बुकस्टोर","i").test(n(msg))),aiCats=explicitCat&&!multiCategoryRequest?[explicitCat]:[...new Set([...(u.categories||[]),...detectedCats])],c=explicitCat&&!multiCategoryRequest?explicitCat:(u.category||explicitCat||(u.followUp?cat(previous):"")),propertyMode=u.intent.startsWith("property_")||isPropertyQuery(msg,u.followUp?previous:""),ct=u.city||(u.followUp?city(previous):""),near=u.landmark||u.area||u.locality||(u.nearRelation?nearTerm(msg):""),locationForFilter=strictLocation(msg),action=String(b?.action||u.action||""),shownList=(Array.isArray(b?.shownPropertyIds)?b.shownPropertyIds:[]).map((x:any)=>String(x)),shownIds=new Set(shownList);
const clientCoords=coords(b?.clientCoords);
const genericNearbyIntent=/(?:\bnear me\b|\bnearby\b|\bnearest\b|mere paas|mere pass|mere aas paas|aas paas|पास में|मेरे पास)/i.test(n(msg))&&!u.landmark&&!u.area&&!u.locality&&!nearTerm(msg);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: nearTerm captures hostel in “Mere paas hostel dikhao,” making this condition false; without GPS, the handler skips the location prompt and searches hostels globally.

Assessment: 🟠 Major · 🔁 Occurrence: Sometimes · 🏷️ Incorrect condition logic

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** supabase/functions/studenthubhelp-chat/index.ts
**Line:** 355:355
**Comment:**
	*Incorrect Condition Logic: `nearTerm` captures `hostel` in “Mere paas hostel dikhao,” making this condition false; without GPS, the handler skips the location prompt and searches hostels globally.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

return await chatResponse({reply,intent:"Combined Budget Plan",primaryTopic:"Hostel + Tiffin Combo Budget",budgetPlan,recommendedProperties:[hostelCard,tiffinCard],recommendations:[hostelCard,tiffinCard],suggestedFollowUps:["Hostel ki full details batao","Tiffin ki full details batao","Aur combo options dikhao"],grounded:true,sessionId,targetCity:ct,targetCategory:"hostel+tiffin"},{headers:H},sessionId,msg);
}
let rows=await multiDirect(aiCats.length?aiCats:(c?[c]:(nearCats.length?nearCats:["hostel"])),ct,u.budgetMax??undefined,u.area||u.locality||undefined,u.gender||genderWanted(msg));
if(clientCoords)for(const p of rows){const d=distanceKm(clientCoords,p);if(d!==undefined)p._distanceKm=d}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: GPS distance only affects ranking; no radius removes distant rows. When no close listing exists, an arbitrary far-away listing can still be returned as a nearby match.

Assessment: 🟠 Major · 🔁 Occurrence: Sometimes · 🏷️ Incorrect condition logic

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** supabase/functions/studenthubhelp-chat/index.ts
**Line:** 448:448
**Comment:**
	*Incorrect Condition Logic: GPS distance only affects ranking; no radius removes distant rows. When no close listing exists, an arbitrary far-away listing can still be returned as a nearby match.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@codeant-ai

codeant-ai Bot commented Nov 9, 2026

Copy link
Copy Markdown

CodeAnt  CodeAnt Nitpicks

6 code suggestions

1. When the trusted Cloudflare IP is absent, callers can rotate sessionId, x-session-id, and x-forwarded-for on every request, giving each hit new keys and bypassing the per-client limits.

Security · supabase/functions/studenthubhelp-chat/index.ts:13


2. Admin chatbot files are absent from this path filter, so a pull request changing only ChatbotAdminControls.tsx or IntelligenceViews.tsx skips this validation workflow entirely.

Incomplete implementation · .github/workflows/chatbot-pr-check.yml:13-19


3. This retry state survives clearConversation, so clearing after a retryable failure leaves the old retry button available to resend the deleted prompt.

Stale reference · ai-chatbot/src/components/ChatWidget.tsx:89


4. When runtime config disables the chatbot, the endpoint returns 503 with its maintenance text in reply; this handler ignores it and shows a generic status error.

Api mismatch · ai-chatbot/src/components/ChatWidget.tsx:164


5. The generated tag sends the chosen primary color as data-color, but the widget never reads that attribute, so changing Primary Theme Color has no effect on the embedded widget.

Api mismatch · ai-chatbot/src/components/EmbedCodeModal.tsx:30


6. The timer is cleared when response headers arrive, before r.json() reads the body; a stalled Gemini response can keep general-chat requests pending past the 8-second deadline.

Possible bug · supabase/functions/studenthubhelp-chat/index.ts:292

@codeant-ai

codeant-ai Bot commented Nov 9, 2026

Copy link
Copy Markdown

CodeAnt  CodeAnt PR Risk

🔴  High Risk

  • The PR should not merge yet because its pull-request workflow exposes a write-capable token while installing PR-controlled dependencies.
  • The hostel-and-tiffin planner promises verified options but can select active, priced listings without checking their verified status.
  • The planner’s separate 70% hostel and 35% tiffin caps exclude valid combinations that fit the overall budget.
  • Nearby searches can return distant listings because device distance affects ranking but does not impose a radius.
  • The React request timeout is cleared when headers arrive, so a stalled response body can leave the chatbot loading indefinitely.

Assessed commit: 1a511c00d518

This branch has not been deployed

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

Labels

size:XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant