Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
e2cd34f
Fix chatbot active listing retrieval, nearby evidence and request limits
StudentHubHelp Nov 8, 2026
ea614ba
Remove duplicate chatbot admin controls instance
StudentHubHelp Nov 8, 2026
d39861f
Connect chatbot admin controls to live Edge Function
StudentHubHelp Nov 8, 2026
8e3ad25
Apply chatbot comparison and retrieval limits
StudentHubHelp Nov 8, 2026
835c930
Harden chatbot admin feature gates and background logging
StudentHubHelp Nov 8, 2026
9238ca3
Tighten chatbot rate-limit identity and config bounds
StudentHubHelp Nov 8, 2026
06c0a49
Add atomic distributed chatbot rate limiting
StudentHubHelp Nov 8, 2026
cd0da17
Fix chatbot syntax and use distributed rate limits
StudentHubHelp Nov 8, 2026
d8b5c9d
Honor chatbot budget planner admin control
StudentHubHelp Nov 8, 2026
e11e4c4
Clarify chatbot AI control label
StudentHubHelp Nov 8, 2026
d86fab1
Harden chatbot runtime config, rate limits and error handling
StudentHubHelp Nov 8, 2026
a8cc46b
Verify chatbot admin settings upsert
StudentHubHelp Nov 8, 2026
eee370b
Add chatbot retry action for transient backend errors
StudentHubHelp Nov 8, 2026
20de096
Reduce chatbot admin config cache staleness
StudentHubHelp Nov 8, 2026
7e96d58
Improve chatbot search pushdown, location labels and Gemini fallback
StudentHubHelp Nov 8, 2026
9acec1c
Align embedded chatbot request timeout to 15 seconds
StudentHubHelp Nov 8, 2026
2a00fa8
Correct rate key return and normalize location aliases
StudentHubHelp Nov 8, 2026
5482758
Bound Gemini calls to shared 12-second request deadline
StudentHubHelp Nov 8, 2026
4fef81b
Fix rate key function and search alias typing
StudentHubHelp Nov 8, 2026
6f97cde
Fail closed when trusted client IP header is unavailable
StudentHubHelp Nov 8, 2026
46ee0c2
Display verified GPS or approximate area match in chatbot cards
StudentHubHelp Nov 8, 2026
7342b33
Harmonize React chatbot timeout and add voice/retry fallbacks
StudentHubHelp Nov 8, 2026
417b42c
Align legacy local chatbot Gemini timeout and clear timer
StudentHubHelp Nov 8, 2026
ffd5c04
Document authoritative Edge Function chatbot architecture
StudentHubHelp Nov 8, 2026
5d93c53
Enforce budget and area-distance integrity in comparison results
StudentHubHelp Nov 8, 2026
223bd8b
Add chatbot Edge Function and React PR validation
StudentHubHelp Nov 8, 2026
c7af7c4
Make legacy server timeout cleanup type-safe
StudentHubHelp Nov 8, 2026
f2c770b
Validate trusted IP and briefly cache fail-closed config
StudentHubHelp Nov 8, 2026
f9e4874
Verify admin settings update under existing RLS policy
StudentHubHelp Nov 8, 2026
3593a23
Resolve chatbot Edge Function type-check errors
StudentHubHelp Nov 8, 2026
525857d
Scope React type-check to chatbot component
StudentHubHelp Nov 8, 2026
6a52597
Push city, area, gender and budget filters into category queries
StudentHubHelp Nov 8, 2026
6005d21
Include structured listing type and nearby coaching in search text
StudentHubHelp Nov 8, 2026
28ca5bb
Run chatbot validation on isolated branch pushes
StudentHubHelp Nov 8, 2026
6cf2d52
Preserve Hindi locality text in database search filters
StudentHubHelp Nov 8, 2026
f68272b
Require explicit area evidence for non-GPS locality matches
StudentHubHelp Nov 8, 2026
dfdbd52
Include hostel type field in gender matching
StudentHubHelp Nov 8, 2026
deb4212
Parse Hindi numeric budget phrases such as 5000 se kam
StudentHubHelp Nov 8, 2026
e190d2a
Restore Vite source entry before chatbot CI build
StudentHubHelp Nov 8, 2026
b3f53a0
Improve chatbot rate-limit fallback, DB timeouts, combo budgets and p…
StudentHubHelp Nov 8, 2026
b36d1f6
Correct combo planner async and regex escaping
StudentHubHelp Nov 8, 2026
e511548
Fix combo budget parsing and response formatting
StudentHubHelp Nov 8, 2026
181834b
Add opt-in GPS location and graceful voice fallback
StudentHubHelp Nov 8, 2026
5b4b871
Add chatbot search regression test suite
StudentHubHelp Nov 8, 2026
9662fb9
Pin production chatbot API to Supabase Edge Function
StudentHubHelp Nov 8, 2026
fc93545
Add dependency audit report and regression script syntax check
StudentHubHelp Nov 8, 2026
80dba35
Enforce exact city boundary in combined budget results
StudentHubHelp Nov 8, 2026
7e42167
Strengthen city/category regression checks and GPS fallback test
StudentHubHelp Nov 8, 2026
db068a4
Add Jhunjhunu/Udaipurwati city parsing and tiffin monthly-plan filtering
StudentHubHelp Nov 8, 2026
c064b3b
Correct Unicode city-boundary regexes
StudentHubHelp Nov 8, 2026
731ebd5
Allow session header in chatbot CORS policy
StudentHubHelp Nov 8, 2026
5996c6b
Make unsupported voice input explain fallback on click
StudentHubHelp Nov 8, 2026
6ce0573
Fix combined budget planner declaration syntax
StudentHubHelp Nov 8, 2026
6eb8fbe
Pin patched Vite and vulnerable transitive dependency overrides
StudentHubHelp Nov 8, 2026
25c33a8
Add safe targeted npm updates and lockfile persistence
StudentHubHelp Nov 8, 2026
4e9c746
Make npm audit a zero-vulnerability CI gate
StudentHubHelp Nov 8, 2026
746158a
chore(chatbot): patch audited dependencies [skip ci]
github-actions[bot] Nov 8, 2026
164e7e7
Enable RLS on private distributed chatbot rate-limit table
StudentHubHelp Nov 8, 2026
3704adb
Align rate-limit migration filename with applied Supabase migration v…
StudentHubHelp Nov 8, 2026
cdec1f5
Remove duplicate pending rate-limit migration file
StudentHubHelp Nov 8, 2026
b4abb7b
Fix combo budget response template literal syntax
StudentHubHelp Nov 8, 2026
2f6a489
Add optional GPS support to public chatbot widget
StudentHubHelp Nov 8, 2026
cece043
Add public widget JavaScript syntax validation
StudentHubHelp Nov 8, 2026
8cff683
Use primary-key cursor pagination for category search
StudentHubHelp Nov 8, 2026
d27e623
Keep legacy Express server out of production build
StudentHubHelp Nov 8, 2026
ab91fa5
Document secure rate-limit fallback and legacy server isolation
StudentHubHelp Nov 8, 2026
3d9fd53
Mark Express API as local-only preview server
StudentHubHelp Nov 8, 2026
7c1f85f
Enforce explicit single-category search and detect intentional multi-…
StudentHubHelp Nov 8, 2026
8ed4101
Correct explicit category detection regex escaping
StudentHubHelp Nov 8, 2026
6d91d55
Use verified monthly tiffin prices only in budget calculations
StudentHubHelp Nov 8, 2026
e4fe3f5
Add combined hostel+tiffin budget regression case
StudentHubHelp Nov 8, 2026
3bc180c
Exclude zero and missing prices from budget search results
StudentHubHelp Nov 8, 2026
651aa4c
Allow honest no-result response for unpriced Piprali hostel budget se…
StudentHubHelp Nov 8, 2026
3efbd01
Validate trusted Cloudflare IP header before using it for rate limits
StudentHubHelp Nov 8, 2026
8bb7de3
Correct whitespace validation for Cloudflare client IP
StudentHubHelp Nov 8, 2026
ee9d8b9
Reject out-of-range GPS coordinates before distance calculations
StudentHubHelp Nov 8, 2026
12af371
Bound total cursor pagination time per category search
StudentHubHelp Nov 8, 2026
a4f8c86
Prioritize explicit current-message category over AI category guesses
StudentHubHelp Nov 8, 2026
e125349
Use first positive verified monthly price across fallback fields
StudentHubHelp Nov 8, 2026
7dd2110
Explain missing monthly-price data when no budget combo is verifiable
StudentHubHelp Nov 8, 2026
1b18713
Parse comma-formatted rupee budgets in combo planner
StudentHubHelp Nov 8, 2026
9ac35be
Wire budget planner action to a fresh chatbot search
StudentHubHelp Nov 8, 2026
1a456f2
Preserve selected city when recalculating hostel and tiffin budget
StudentHubHelp Nov 8, 2026
c82504b
Lock production React chatbot to Supabase Edge Function URL
StudentHubHelp Nov 8, 2026
1c2035b
Verify no localhost API references and no Express server production b…
StudentHubHelp Nov 8, 2026
8938619
Correct localhost API grep expression
StudentHubHelp Nov 8, 2026
878f3a5
Require category metadata in search regression assertions
StudentHubHelp Nov 8, 2026
a3039b6
Clean stale Express bundle before static production build
StudentHubHelp Nov 8, 2026
34c0236
Fix embed generator to point at Supabase chatbot Edge Function
StudentHubHelp Nov 8, 2026
c1f2f3b
Add optional GPS coordinates to bundled public chatbot widget
StudentHubHelp Nov 8, 2026
fc41c56
Validate bundled public widget JavaScript syntax
StudentHubHelp Nov 8, 2026
d31a1db
Gracefully handle geolocation API exceptions
StudentHubHelp Nov 8, 2026
b480ade
Gracefully handle geolocation API exceptions
StudentHubHelp Nov 8, 2026
de4b1bc
Gracefully handle geolocation API exceptions
StudentHubHelp Nov 8, 2026
1a511c0
Verify combo budget breakdown sums to its total
StudentHubHelp Nov 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions .github/workflows/chatbot-pr-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
name: Chatbot PR validation

on:
push:
branches:
- fix/chatbot-reliability-security
paths:
- 'supabase/functions/studenthubhelp-chat/**'
- 'supabase/migrations/*chatbot*'
- 'ai-chatbot/**'
- 'widget.js'
- '.github/workflows/chatbot-pr-check.yml'
pull_request:
paths:
- 'supabase/functions/studenthubhelp-chat/**'
- 'supabase/migrations/*chatbot*'
- 'ai-chatbot/**'
- 'widget.js'
- '.github/workflows/chatbot-pr-check.yml'

permissions:
contents: write
Comment on lines +21 to +22

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
👍 | 👎


jobs:
edge-function-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: denoland/setup-deno@v2
with:
deno-version: v2.x
- name: Type-check Supabase Edge Function
run: deno check supabase/functions/studenthubhelp-chat/index.ts

react-chatbot-check:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ai-chatbot
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- uses: actions/setup-node@v6
with:
node-version: 20
cache: npm
cache-dependency-path: ai-chatbot/package-lock.json
- name: Install dependencies
run: npm install --no-audit
- name: Update only audited vulnerable packages
run: npm update vite body-parser proxy-addr qs source-map-js --no-audit
- name: Persist patched dependency lockfile
env:
TARGET_BRANCH: ${{ github.head_ref || github.ref_name }}
HEAD_REPOSITORY: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
run: |
if [ "$HEAD_REPOSITORY" = "$GITHUB_REPOSITORY" ] && [ -n "$TARGET_BRANCH" ]; then
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
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
👍 | 👎

fi
fi
- name: Audit dependency tree
run: npm audit
- name: Report dependency advisories
if: always()
run: |
npm audit --json > /tmp/studenthubhelp-npm-audit.json || true
node - <<'NODE'
const fs = require('fs');
const report = JSON.parse(fs.readFileSync('/tmp/studenthubhelp-npm-audit.json', 'utf8'));
const vulnerabilities = report.vulnerabilities || {};
const entries = Object.entries(vulnerabilities);
console.log('npm audit summary:', JSON.stringify(report.metadata?.vulnerabilities || {}));
for (const [name, item] of entries) {
console.log(JSON.stringify({
name,
severity: item.severity,
range: item.range,
direct: item.isDirect,
fixAvailable: item.fixAvailable,
via: item.via
}));
}
NODE
- name: Validate regression scripts and production API references
run: |
node --check tests/chatbot-regression.mjs
node --check ../widget.js
node --check public/widget.js
if grep -R -nE 'https?://(localhost|127\.0\.0\.1):3000' src; then echo 'Local Express API reference found in client source'; exit 1; fi
- name: Type-check React chatbot component
run: npx tsc --noEmit --skipLibCheck --jsx react-jsx --target ES2020 --module ESNext --moduleResolution bundler --allowImportingTsExtensions --types vite/client src/components/ChatWidget.tsx
- name: Restore Vite source entry for validation
run: |
cat > index.html <<'EOF'
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>StudentHubHelp AI Chatbot</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
EOF
- name: Build chatbot
run: |
npm run build
test ! -f dist/server.cjs
9 changes: 5 additions & 4 deletions admin/src/components/ChatbotAdminControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,11 @@ export const ChatbotAdminControls: React.FC<ChatbotAdminControlsProps> = ({
const { data: userData } = await supabase.auth.getUser();
const updatedBy = userData.user?.email || 'admin';
const payload = { ...config, updated_by: updatedBy, updated_at: new Date().toISOString() };
const { error } = await supabase.from('chatbot_admin_config').update(payload).eq('id', 1);
const { data, error } = await supabase.from('chatbot_admin_config').update(payload).eq('id', 1).select('id, updated_at').single();
if (error) throw error;
setConfig(payload);
setMessage('AI control settings saved to Supabase.');
if (!data || Number(data.id) !== 1) throw new Error('Settings save verify nahi ho payi. Config row id=1 missing ya access denied ho sakta hai.');
setConfig({ ...payload, updated_at: data.updated_at || payload.updated_at });
setMessage('AI control settings saved and verified in Supabase.');
} catch (e: any) {
setMessage(e?.message || 'Unable to save AI controls.');
} finally {
Expand Down Expand Up @@ -241,7 +242,7 @@ export const ChatbotAdminControls: React.FC<ChatbotAdminControlsProps> = ({
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-3">
{[
['enabled', 'AI assistant enabled', ShieldCheck],
['ai_rerank_enabled', 'Gemini AI reranking', Brain],
['ai_rerank_enabled', 'Gemini AI response enhancement', Brain],
['lead_capture_enabled', 'Lead capture', SlidersHorizontal],
['comparison_enabled', 'Live comparison mode', SlidersHorizontal],
['budget_planner_enabled', 'Live budget planner', SlidersHorizontal],
Expand Down
2 changes: 1 addition & 1 deletion admin/src/components/IntelligenceViews.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1272,7 +1272,7 @@ export const IntelligenceViews: React.FC<IntelligenceViewsProps> = ({
</p>
</div>

<ChatbotAdminView /><ChatbotAdminControls />
<ChatbotAdminView />
<ChatbotAdminControls showAiControls />
</div>
);
Expand Down
1 change: 1 addition & 0 deletions ai-chatbot/.env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_CHAT_API_URL=https://idurlccrarznnnqixxsd.supabase.co/functions/v1/studenthubhelp-chat
41 changes: 19 additions & 22 deletions ai-chatbot/README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,36 @@
# StudentHubHelp AI Chatbot

Production-oriented StudentHubHelp AI chatbot based on Gemini 3.8 Flash and live Supabase data.
StudentHubHelp's public chatbot is served by the Supabase Edge Function and reads active listings from the category-specific Supabase tables.

## Data rule
## Production request path

Property recommendations are loaded from the StudentHubHelp public property tables:
- Public website embed: `widget.js` -> `/functions/v1/studenthubhelp-chat`
- React chatbot: `ai-chatbot/src/components/ChatWidget.tsx` -> the same Edge Function
- Edge Function: authoritative runtime config, rate limits, deterministic listing search, and optional Gemini response enhancement
- Supabase: `hostels`, `tiffins`, `libraries`, `cafes`, and `bookstores`

- `hostels`
- `tiffins`
- `libraries`
- `cafes`
- `bookstores`
Both browser clients use the same production endpoint. Do not point either client at the legacy Express `/api/chat` route.

Only rows whose `status` is `active` are exposed to the chatbot. No property records, prices, ratings, contacts or recommendations are hardcoded as demo data.
## Database and security

- Only rows with `status = 'active'` are eligible for public recommendations.
- The Edge Function uses the private `chatbot_rate_limits` table through the `consume_chatbot_rate_limit` security-definer RPC. Apply the checked-in migration before deploying the Edge Function version that calls it.
- Keep the Supabase service-role key server-side only. Browser clients use the public/publishable key.
- The chatbot fails closed when its admin config is missing/unavailable. If Cloudflare's client-IP header is absent, it falls back to lower-threshold session/user-agent and explicitly untrusted proxy keys; this fallback is weaker than a verified edge IP and must be checked in staging.

## Environment

Set:
For the Edge Function, configure the Supabase URL/key and Gemini key as Supabase Function secrets. The React build accepts `VITE_CHAT_API_URL` and `VITE_SUPABASE_ANON_KEY`; the default chat URL is the production Edge Function.

- `GEMINI_API_KEY`
- `SUPABASE_URL`
- `SUPABASE_ANON_KEY`
- `APP_URL` (optional)
## Legacy Express preview

The Supabase key is used server-side for public active-listing reads. Never expose a service-role key in browser code.
`server.ts` and its `/api/*` routes are a legacy local preview harness, not the production source of truth. Its config and lead arrays are in-memory and reset when the process restarts. Do not deploy those endpoints as a public production API or use them for authoritative chatbot settings, leads, or property data.

## Local run
Run the React UI locally with `npm run dev`. To intentionally start the isolated legacy Express preview, use `npm run dev:legacy-server`. The production build is static Vite output only; it does not bundle `server.ts` or the legacy `/api/*` routes.

```bash
npm install
npm run dev
# Optional legacy preview only:
npm run dev:legacy-server
```

## Production architecture

GitHub Pages / public website -> embedded `public/widget.js` -> deployed Node/Express API -> Gemini + Supabase.

The current project is prepared as the chatbot application. Public-site embedding and the admin AI section should be integrated after the live backend deployment endpoint is chosen.
54 changes: 21 additions & 33 deletions ai-chatbot/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 13 additions & 6 deletions ai-chatbot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "tsx server.ts",
"build": "vite build && esbuild server.ts --bundle --platform=node --format=cjs --packages=external --sourcemap --outfile=dist/server.cjs",
"start": "node dist/server.cjs",
"dev": "vite",
"build": "npm run clean && vite build",
"start": "vite preview --host 0.0.0.0",
"preview": "vite preview",
"clean": "rm -rf dist server.js",
"lint": "tsc --noEmit"
"lint": "tsc --noEmit",
"dev:legacy-server": "tsx server.ts"
},
"dependencies": {
"@google/genai": "^2.4.0",
Expand All @@ -18,7 +19,7 @@
"lucide-react": "^0.546.0",
"react": "^19.0.1",
"react-dom": "^19.0.1",
"vite": "^6.2.3",
"vite": "^6.4.4",
"express": "^4.21.2",
"dotenv": "^17.2.3",
"motion": "^12.23.24"
Expand All @@ -30,7 +31,13 @@
"tailwindcss": "^4.1.14",
"tsx": "^4.21.0",
"typescript": "~5.8.2",
"vite": "^6.2.3",
"vite": "^6.4.4",
"@types/express": "^4.17.21"
},
"overrides": {
"body-parser": "^1.20.9",
"proxy-addr": "^2.0.8",
"qs": "^6.16.1",
"source-map-js": "^1.2.2"
}
}
Loading
Loading