A production-grade complaint management system with AI-powered chat interface, voice notes, escalation workflows, and email notifications. Built with Go backend and React frontend.
AI Neta enables citizens to file complaints through an intuitive chat interface, track their status, and receive updates. Authorities can manage assigned complaints, update statuses, and escalate issues when needed. The system includes automated escalation, email notifications (shadow mode for pilot), and public case pages for transparency.
- Chat-based complaint filing - Natural language conversation with AI assistant
- Phone OTP authentication - Secure login via phone number verification
- Live photo capture - Camera-based evidence capture (gallery option available)
- Voice notes - Optional voice recording attached to complaints
- GPS location - Automatic location capture for complaints
- Status tracking - Real-time complaint status and timeline
- Public case pages - Shareable complaint pages (no PII exposed)
- Dashboard - View only assigned complaints
- Status management - Update complaint status with mandatory reasons
- Internal notes - Add notes visible to authority users
- Escalation handling - Manage escalated complaints
- Automated escalation - Time-based escalation with configurable SLAs
- Email notifications - Shadow mode (all emails to pilot inbox) or production SendGrid
- Audit trail - Complete status history with actor tracking
- Abuse prevention - Rate limiting and duplicate detection
- Public API - Shareable case pages by complaint number
finalneta/
├── backend/
│ ├── main.go # Application entry point
│ ├── config/ # Configuration management
│ ├── handler/ # HTTP request handlers
│ ├── service/ # Business logic layer
│ ├── repository/ # Database access layer
│ ├── models/ # Data models (entities, DTOs)
│ ├── routes/ # Route configuration
│ ├── middleware/ # Auth, CORS middleware
│ ├── worker/ # Background workers (escalation, notifications)
│ ├── notification/ # Email sender (SendGrid support)
│ ├── migrations/ # Database migrations
│ └── cmd/ # CLI tools (verify_escalation)
├── frontend/
│ ├── src/
│ │ ├── pages/ # Main pages (Chat, Dashboard, etc.)
│ │ ├── screens/ # Screen components
│ │ ├── components/ # Reusable components
│ │ ├── stores/ # Zustand state management
│ │ ├── services/ # API client
│ │ └── utils/ # Utilities
│ └── package.json
└── docs/ # Documentation
- Go 1.21+ (backend)
- Node.js 18+ and npm (frontend)
- MySQL 5.7+ or MariaDB 10.3+
- Git
- Clone repository
git clone <repository-url>
cd finalneta- Install Go dependencies
go mod download- Configure environment (create
.envfile)
# Database
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASSWORD=your_password
DB_NAME=finalneta
# Server
SERVER_HOST=0.0.0.0
SERVER_PORT=8080
# JWT
JWT_SECRET=your-secret-key-change-in-production
# Email (optional - for production)
EMAIL_MODE=shadow # shadow | production
EMAIL_SHADOW_ADDRESS=aineta502@gmail.com
SENDGRID_API_KEY=your-sendgrid-key # Optional: for real email delivery
SENDGRID_FROM_EMAIL=noreply@aineta.in
SENDGRID_FROM_NAME=AI Neta
# Pilot/Testing
ADMIN_TOKEN=pilot-admin-qa # For admin endpoints
TEST_ESCALATION_OVERRIDE_MINUTES=1 # Override escalation SLA for testing
ESCALATION_WORKER_INTERVAL_SECONDS=30
# Frontend URL (for email links)
FRONTEND_URL=http://localhost:3000
# Uploads
UPLOAD_BASE_PATH=uploads # Default: uploads/- Run database migrations
# Apply migrations in order:
mysql -u root -p finalneta < migrations/0001_complaint_status_history_audit_columns.sql
mysql -u root -p finalneta < migrations/0002_authority_pilot_tables.sql
mysql -u root -p finalneta < migrations/0003_officers_authority_level.sql
mysql -u root -p finalneta < migrations/0004_add_verified_status_enum.sql
mysql -u root -p finalneta < migrations/0005_complaint_voice_notes.sql
mysql -u root -p finalneta < migrations/0006_email_logs_status.sql- Start backend
go run .Backend runs on http://localhost:8080
- Navigate to frontend directory
cd frontend- Install dependencies
npm install- Configure environment (create
frontend/.env)
VITE_API_BASE_URL=http://localhost:8080/api/v1- Start development server
npm run devFrontend runs on http://localhost:3000 (or next available port)
POST /api/v1/users/otp/send
- Send OTP to phone number
- Body:
{ "phone_number": "9876543210" } - Response:
{ "success": true, "otp": "123456" }(dev mode includes OTP)
POST /api/v1/users/otp/verify
- Verify OTP and get JWT token
- Body:
{ "phone_number": "9876543210", "otp": "123456" } - Response:
{ "success": true, "token": "jwt...", "user_id": 1 }
POST /api/v1/complaints
- Create new complaint
- Headers:
Authorization: Bearer <token> - Body:
{ "title": "...", "description": "...", "location_id": 1, "latitude": 28.6, "longitude": 77.2, "attachment_urls": ["url"], ... } - Response:
{ "complaint_id": 1, "complaint_number": "COMP-20260215-abc123", "status": "submitted" }
GET /api/v1/complaints
- Get user's complaints list
- Headers:
Authorization: Bearer <token>
GET /api/v1/complaints/{id}
- Get complaint details (owner only)
- Headers:
Authorization: Bearer <token>
GET /api/v1/complaints/{id}/timeline
- Get status timeline
- Headers:
Authorization: Bearer <token>
POST /api/v1/complaints/{id}/voice
- Upload voice note (owner only, overwrites existing)
- Headers:
Authorization: Bearer <token>,Content-Type: audio/webmoraudio/wav - Body: Raw audio blob
- Response:
{ "message": "Voice note attached", "complaint_id": 1 }
POST /api/v1/authority/login
- Authority login
- Body:
{ "email": "officer@example.com", "password": "password" } - Response:
{ "success": true, "token": "jwt...", "officer_id": 1 }
GET /api/v1/authority/complaints
- Get assigned complaints
- Headers:
Authorization: Bearer <authority_token>
POST /api/v1/authority/complaints/{id}/status
- Update complaint status
- Headers:
Authorization: Bearer <authority_token> - Body:
{ "new_status": "under_review", "reason": "..." }(reason required)
POST /api/v1/authority/complaints/{id}/note
- Add internal note
- Headers:
Authorization: Bearer <authority_token> - Body:
{ "note_text": "...", "is_visible_to_citizen": false }
GET /api/v1/public/complaints/by-number/{complaint_number}
- Get public case page (no auth required)
- Response:
{ "complaint_number": "...", "current_status": "...", "timeline": [...] } - No PII, GPS, or images exposed
POST /api/v1/complaints/{id}/verify
- Verify complaint (admin only)
- Headers:
X-Admin-Token: <ADMIN_TOKEN>
POST /api/v1/escalations/process
- Trigger escalation worker manually (admin only)
- Headers:
X-Admin-Token: <ADMIN_TOKEN>
- Phone number + OTP verification
- JWT token stored in
localStorage(auth_token) - Token includes
user_idandactor_type: "user" - Middleware validates token and sets
user_idin context
- Email + password login
- JWT token includes
officer_id,authority_level,actor_type: "authority" - Middleware validates token and sets
officer_idin context
- Citizen tokens rejected on authority endpoints
- Authority tokens rejected on citizen endpoints
- CORS configured for frontend origin
- No PATCH endpoints exposed (only POST for status updates)
- All emails sent to:
aineta502@gmail.com(configurable viaEMAIL_SHADOW_ADDRESS) - Email types: Assignment, Escalation, Resolution
- Logging: All emails logged to
email_logstable with status (sent/failed) and error messages - Non-blocking: Email failures never break complaint flows
- Set
EMAIL_MODE=productionandSENDGRID_API_KEY - Emails sent via SendGrid API
- Still respects shadow address if
EMAIL_MODE=shadow
- Assignment: When complaint is assigned to department
- Escalation: When complaint escalates to next level
- Resolution: When authority updates status to resolved/closed
complaints- Main complaint recordscomplaint_status_history- Status change audit trailcomplaint_voice_notes- Voice attachments (one per complaint)complaint_attachments- Photo attachmentsemail_logs- Email delivery logscomplaint_escalations- Escalation recordsusers- Citizen users (phone-based)officers- Authority officersauthority_credentials- Officer login credentials
Run migrations in order (0001_*.sql through 0006_*.sql). See migrations/ directory.
- Automatic escalation based on SLA (time since status change)
- Escalation levels: L0 → L1 → L2 → L3
- Rules: Configurable per department/location
- Worker: Runs every 30 seconds (configurable)
- Testing: Use
TEST_ESCALATION_OVERRIDE_MINUTES=1for 1-minute SLA override
go run ./cmd/verify_escalationRuns one escalation cycle and reports results.
See docs/QA_WHAT_TO_DO_AND_CHECK.md for manual testing steps.
ADMIN_TOKEN=pilot-admin-qa
TEST_ESCALATION_OVERRIDE_MINUTES=1
ESCALATION_WORKER_INTERVAL_SECONDS=15Create complaint (after OTP auth)
curl -X POST http://localhost:8080/api/v1/complaints \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"title": "Road pothole",
"description": "Large pothole on Main Street",
"location_id": 1,
"latitude": 28.6139,
"longitude": 77.2090,
"attachment_urls": ["data:image/jpeg;base64,..."],
"priority": "medium",
"public_consent_given": true
}'Get public case
curl http://localhost:8080/api/v1/public/complaints/by-number/COMP-20260215-abc123- Check MySQL is running
- Verify
.envfile exists with correct DB credentials - Ensure migrations are applied
- Check backend is running on port 8080
- Verify
VITE_API_BASE_URLinfrontend/.env - Check browser console for API errors
- Ensure phone is verified (OTP flow completed)
- Check
email_logstable for status (sent/failed) - Verify
EMAIL_SHADOW_ADDRESSis set - If using SendGrid, verify
SENDGRID_API_KEYis valid
- Ensure
TEST_ESCALATION_OVERRIDE_MINUTES=1for testing - Check complaint has
assigned_department_id - Verify complaint status is eligible (verified, under_review, in_progress)
- Check
complaint_escalationstable for records
- Backend: Go modules, clean architecture (handler → service → repository)
- Frontend: React + Vite, Zustand for state, React Router
- State Management: Zustand stores (
chatStore,authStore) - API Client: Centralized in
frontend/src/services/api.js
- Go: Standard formatting (
go fmt) - JavaScript: ESLint configured
- Commits: Conventional commits preferred
[Your License Here]
[Contributing guidelines]
For issues and questions, see docs/ directory for detailed documentation.