Skip to content

PRAZPC/bachao

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

44 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Bachao mobile app

🚨 Bachao

Built to reach help when the network can't.

Emergency Reporting & Response Coordination β€” online and offline

Report an emergency, reach the nearest guardian, and get help even when there's no internet β€” over a single compact SMS.

Python FastAPI Expo React Native TypeScript License


## Offline SMS Demo

When there's no data connection, Bachao encodes your emergency type and location into a tiny SMS and hands it to your phone's messaging app. Watch it in action:

Bachao offline SMS demo

β–Ά Play the full-quality video (offline-demo.mp4) for sound and higher resolution.


Why Bachao?

Emergencies don't wait for good signal. Bachao is built around a simple idea: a single SMS should be enough to summon help. It combines three tightly-linked channels so a citizen in distress always has a path to a responder.

Channel What it does
Mobile app Registration, live map-based SOS, and an offline SMS fallback
Backend Users, guardians, incidents, dispatch, dashboards, real-time WebSockets
SMS protocol Packs emergency type + geohashed location into one short message

What the System Does

  • Citizen registration with phone verification, profile details, and identity photo uploads
  • JWT login using phone number plus OTP
  • Guardian registration with certificate upload and admin approval
  • Guardian availability, location updates, and incident-response tracking
  • App-created SOS incidents with live location
  • SMS-created incidents from compact messages such as SMS-M-dr5ru7b2n0-X9K2Q1
  • Nearest-guardian lookup using Haversine distance
  • Dispatcher/admin incident visibility and manual guardian assignment
  • HTML backend dashboards for overview, users, incoming reports, and assignments
  • WebSocket broadcasts for incident creation and guardian pings
  • Full middleware stack: request IDs, timing, logging, rate limiting, validation, compression, error handling, and metrics

Architecture at a Glance

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    Online SOS ──▢  β”‚                          β”‚
                    β”‚       FastAPI Backend    │──▢ Nearest Guardians
     Offline SMS ─▢ β”‚   users Β· incidents Β·    │──▢  WebSocket broadcasts
      (via gateway) β”‚   guardians Β· dispatch   │──▢  Admin dashboards
                    β”‚                          β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                          πŸ—„ SQLite (bachao.db)
  • Online path: app β†’ POST /api/sos/ β†’ incident created β†’ nearby guardians found β†’ real-time broadcast.
  • Offline path: app encodes SMS-{TYPE}-{GEOHASH}-{ID} β†’ SMS gateway β†’ POST /api/sms/ingress β†’ incident created β†’ real-time broadcast.

Repository Layout

D:\bachao
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ app/main.py            # FastAPI app, middleware, routers, startup DB init
β”‚   β”œβ”€β”€ api/                   # REST and HTML dashboard routes
β”‚   β”œβ”€β”€ core/                  # config, auth, database session, geohash, DB init
β”‚   β”œβ”€β”€ middleware/            # request/response middleware stack
β”‚   β”œβ”€β”€ model/                 # Pydantic schemas and SQLAlchemy models
β”‚   β”œβ”€β”€ services/              # user, guardian, incident, dispatcher, SMS decoder logic
β”‚   β”œβ”€β”€ template/              # Jinja2 dashboard templates
β”‚   β”œβ”€β”€ ws/                    # WebSocket endpoints
β”‚   β”œβ”€β”€ run_server.py          # local backend runner
β”‚   β”œβ”€β”€ assign_admin.py        # role/admin management helper for SQLite users
β”‚   β”œβ”€β”€ requirements.txt       # Python dependencies
β”‚   └── Dockerfile             # backend container image
β”œβ”€β”€ frontend/
β”‚   └── app/
β”‚       β”œβ”€β”€ apps/expo-app/     # Expo Router mobile application
β”‚       β”œβ”€β”€ packages/          # workspace packages: UI, Supabase, auth/account
β”‚       β”œβ”€β”€ tooling/           # shared ESLint, Prettier, Tailwind, TS configs
β”‚       β”œβ”€β”€ package.json       # frontend monorepo scripts
β”‚       β”œβ”€β”€ pnpm-workspace.yaml
β”‚       └── turbo.json         # Turborepo task config
β”œβ”€β”€ packages/
β”‚   └── sms-core/              # shared SMS protocol docs and encode/decode utilities
β”œβ”€β”€ docker-compose.yml         # backend + (stale) frontend-dev service reference
β”œβ”€β”€ package.json               # root convenience scripts (partially stale)
└── README.md

Generated/runtime directories present in this checkout (node_modules, backend/venv, backend/uploads, .expo, .turbo, caches, bachao.db) should normally be git-ignored.


Technology Stack

Backend

  • Python 3.11
  • FastAPI + Starlette
  • Uvicorn
  • SQLAlchemy
  • SQLite (default)
  • Pydantic v2
  • Jinja2 templates
  • JWT via python-jose
  • Uploads via python-multipart

Frontend

  • Expo SDK 52
  • React Native 0.76
  • Expo Router
  • TypeScript
  • Turborepo + pnpm workspaces
  • NativeWind / Tailwind
  • React Query
  • AsyncStorage
  • Expo Location
  • Mapbox / OpenStreetMap
  • Supabase scaffolding

Shared SMS package

  • TypeScript encoder
  • Python decoder
  • Geohash-based location encoding / decoding

Quick Start

Backend

cd backend
python -m venv venv
venv\Scripts\activate          # Windows
python -m pip install -r requirements.txt
python run_server.py

Backend runs at http://localhost:8000

URL Purpose
http://localhost:8000/ Root
http://localhost:8000/docs Interactive API docs
http://localhost:8000/api/health Health check
http://localhost:8000/api/backend-dashboard Admin dashboard
http://localhost:8000/api/backend-dashboard/incoming-reports Incoming reports

Frontend

The active Expo workspace lives under frontend/app (not directly under frontend).

cd frontend/app
pnpm install

cd apps/expo-app
pnpm start

Or run through the monorepo:

cd frontend/app
pnpm dev

Useful Expo commands: pnpm android, pnpm ios, pnpm web, pnpm typecheck, pnpm lint.

The root frontend:dev script runs cd frontend && npx expo start, but the active app is under frontend/app/apps/expo-app. Prefer the commands above until the root scripts are updated.


Environment Configuration

Backend β€” backend/.env

API_PREFIX=/api
DEBUG=true
SECRET_KEY=replace-this-in-development-too
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
DATABASE_URL=sqlite:///./bachao.db

DATABASE_URL is defined in settings, but the active SQLAlchemy engine currently uses the hardcoded value in backend/core/database.py. Changing DATABASE_URL alone won't move the database.

Frontend β€” frontend/app/apps/expo-app/.env

EXPO_PUBLIC_API_URL=http://localhost:8000
EXPO_PUBLIC_API_PREFIX=/api
EXPO_PUBLIC_WS_URL=ws://localhost:8000
EXPO_PUBLIC_SMS_FORWARDING_RECEIVER="+9779863514215"
EXPO_PUBLIC_SUPABASE_API_URL=
EXPO_PUBLIC_SUPABASE_ANON_KEY=
Target API / WS URL
Android emulator http://10.0.2.2:8000 / ws://10.0.2.2:8000
Physical device http://192.168.x.x:8000 / ws://192.168.x.x:8000 (LAN IP)

Do not commit real secrets or production tokens.


πŸ“‘ SMS Protocol

The emergency SMS format packs everything into one short string:

SMS-{TYPE}-{GEOHASH}-{ID}

The shared package spec also documents a legacy SOS-{TYPE}-{GEOHASH}-{ID} form. The backend local decoder accepts both SMS and SOS; the current mobile app uses SMS.

Code Emergency Type
M πŸš‘ Medical
P πŸš“ Police
F πŸ”₯ Fire
G πŸ†˜ General
N πŸŒͺ️ Natural Disaster
A πŸ’₯ Accident

Example

SMS-M-tudr4et3f9-X9K2Q1

app/utils/smsEncoder.ts encodes the emergency type and current/cached coordinates into a 10-character geohash. The backend decoder turns that geohash back into coordinates before creating the incident.


Backend API

All REST routes are mounted under /api.

Health
GET /api/health          β†’  {"status": "ok"}
Users & Authentication
POST /api/users/register/step1     # JSON phone verification  (dev OTP: 123456)
POST /api/users/register/step2     # form: session_id, name, age, email, nid?
POST /api/users/register/step3     # multipart photos β†’ creates user, returns token
POST /api/users/login              # form: phone_number, otp  (dev OTP: 1234)
GET  /api/users/profile            # Authorization: Bearer <token>

Registration is a three-step flow; authenticated routes use Authorization: Bearer <token>.

Guardians
POST /api/guardians/register              # multipart certificate_photo (starts pending)
GET  /api/guardians/profile
POST /api/guardians/respond/{incident_id} # ACCEPTED | DECLINED | ARRIVED | COMPLETED
POST /api/guardians/location
POST /api/guardians/availability
GET  /api/guardians/pending               # admin only
POST /api/guardians/approve/{guardian_id} # admin only

When a guardian accepts an incident, it is assigned to that guardian and moved to IN_PROGRESS.

SOS
POST /api/sos/
{ "type": "Medical", "lat": 27.7172, "lng": 85.3240, "device_id": "device-id" }

Creates an APP incident β†’ finds nearby available guardians β†’ broadcasts INCIDENT_CREATED and GUARDIANS_PINGED.

SMS Ingress
POST /api/sms/ingress
{ "sender": "+9779812345678", "body": "SMS-M-tudr4et3f9-X9K2Q1" }

Decodes the body β†’ maps code to incident type β†’ decodes geohash to lat/lng β†’ links to a registered user if the sender exists β†’ creates an SMS incident β†’ broadcasts events.

Dispatcher
GET /api/dispatch/incidents
GET /api/dispatch/incidents/active

Visibility by role β€” ADMIN/DISPATCHER: all Β· GUARDIAN: active Β· USER: own incidents only.

Backend Dashboard
GET  /api/backend-dashboard
GET  /api/backend-dashboard/stats
GET  /api/backend-dashboard/incidents
GET  /api/backend-dashboard/users
GET  /api/backend-dashboard/guardians
GET  /api/backend-dashboard/incoming-reports
POST /api/backend-dashboard/assign-guardian
POST /api/backend-dashboard/unassign-guardian
GET  /api/backend-dashboard/incident/{incident_id}

These routes do not enforce authentication in code. Put them behind auth or network controls before production.

Metrics
GET /api/metrics
GET /api/metrics/summary
GET /api/metrics/endpoint/{endpoint}

Generated by APIMetricsMiddleware and stored in memory for the current process.

WebSocket API

Mounted outside /api:

ws://localhost:8000/ws/incidents
ws://localhost:8000/ws/guardians
{
  "event": "INCIDENT_CREATED",
  "incident": {
    "id": 1, "external_id": "uuid", "type": "Medical",
    "latitude": 27.7172, "longitude": 85.3240,
    "source": "APP", "status": "active", "created_at": "..."
  },
  "guardians_notified": 3
}

Guardian broadcasts include GUARDIANS_PINGED with the incident and guardian IDs.


Data Model

SQLAlchemy models live in backend/model/database_models.py.

  • User β€” phone, email, name, age, optional NID, role, identity file paths, verification/active state, timestamps. Roles: USER, GUARDIAN, DISPATCHER, ADMIN.
  • RegistrationSession β€” multi-step registration state before a real User is created (profile fields, uploads, guardian cert fields, completion, expiry).
  • Guardian β€” links to a user; certificate data, approval state, availability, current location, last update, response metrics.
  • Incident β€” emergency type, coordinates, source (APP/SMS), reporter relationship, status, description, assignment, response times. Statuses: ACTIVE, IN_PROGRESS, RESOLVED, CANCELLED. Types: Medical, Police, Fire, General, Natural Disaster, Accident.
  • GuardianResponse β€” a guardian's response (ACCEPTED, DECLINED, ARRIVED, COMPLETED) with estimated arrival, response location, notes.

Middleware Stack

Configured in backend/app/main.py, in order:

Middleware Responsibility
RequestIDMiddleware Adds/preserves X-Request-ID
TimingMiddleware Request timing; logs slow requests
LoggingMiddleware Logs method, path, status, IP, request ID, duration
RateLimiterMiddleware In-memory per-IP limits (60/min, 1000/hr)
APIMetricsMiddleware Request totals, status counts, response times, error rates
APIVersioningMiddleware Defaults to API version 1
RequestValidationMiddleware Content type, size, JSON syntax, SQLi/XSS patterns
CompressionMiddleware gzip for larger responses
ErrorHandlerMiddleware Consistent JSON errors for unhandled exceptions
CORSMiddleware Permits any http/https origin in development

Rate-limiter and metrics storage are in-memory. For multi-process/multi-server deployments, back them with Redis or another shared store.


Mobile App Flows

The Expo app lives in frontend/app/apps/expo-app. Entry route redirects to /(auth)/sign-up.

Authentication / onboarding: phone entry β†’ OTP β†’ user-type selection (citizen, guardian, volunteer, organization) β†’ profile form & document upload β†’ submitted/contact screens for non-citizen roles.

Online flow: map centered on the user (Kathmandu fallback) via LocationService β†’ emergency categories in a draggable bottom sheet β†’ selecting one routes into the emergency-selection flow.

Offline / SMS flow: select emergency type β†’ sub-type β†’ SOS preview loads fresh/cached location β†’ encode SMS-{TYPE}-{GEOHASH}-{ID} β†’ open SMS composer to the configured receiver β†’ copy manually if the composer can't open.

Location behavior: Expo Location (foreground permission) Β· caches last location in AsyncStorage (max age 30 min) Β· prefers fresh, falls back to cached, then to Kathmandu coordinates.

Network behavior: useNetworkStatus uses @react-native-community/netinfo; offline UI stays available; location refresh is disabled while offline.

Shared workspace packages: @kit/ui, @kit/supabase, @kit/auth, @kit/account, and tooling/* shared configs. Bachao-specific screens currently live directly inside apps/expo-app/app.


End-to-End Flows

Mobile app SOS flow
  1. User logs in and receives a JWT.
  2. App sends POST /api/sos/ with type, lat, lng, device ID.
  3. Backend creates an Incident with source APP.
  4. Backend finds approved, available guardians within the configured distance.
  5. Backend broadcasts to /ws/incidents and /ws/guardians.
  6. Dispatchers/admins view it in /api/dispatch/incidents or the HTML dashboard.
  7. Guardians respond via /api/guardians/respond/{incident_id}; an accepted guardian becomes assigned.
Offline SMS flow
  1. User selects emergency type and sub-type in the offline UI.
  2. App loads fresh, cached, or fallback location.
  3. App encodes SMS-{TYPE}-{GEOHASH}-{ID}.
  4. App opens the SMS composer to the configured forwarding receiver.
  5. SMS gateway posts the received message to /api/sms/ingress.
  6. Backend decodes the message and creates an SMS incident.
  7. Backend broadcasts incident and guardian ping events.
Dashboard assignment flow
  1. Admin opens /api/backend-dashboard/incoming-reports.
  2. Dashboard loads incidents and available approved guardians.
  3. Admin posts incident_id + guardian_id to /api/backend-dashboard/assign-guardian.
  4. Backend sets the incident to IN_PROGRESS and marks the guardian unavailable.
  5. Admin can unassign later β€” incident returns to ACTIVE, guardian becomes available again.

Docker

Backend-only build (recommended for now):

docker build -t bachao-backend ./backend
docker run --rm -p 8000:8000 bachao-backend

The root docker-compose.yml defines backend and frontend-dev, but frontend-dev references a missing ./frontend/Dockerfile.dev. The full compose file won't build until that Dockerfile is added or the frontend service is removed.


Admin Role Management

Use backend/assign_admin.py to inspect users and update roles in SQLite (run from backend):

python assign_admin.py --list
python assign_admin.py --user-id 1
python assign_admin.py --phone 9812345678
python assign_admin.py --role DISPATCHER --user-id 1
python assign_admin.py --remove-admin 1

After changing a role, the user must log in again so their JWT carries the new role.


Testing & Verification

# Backend
cd backend && python -m pytest

# Frontend
cd frontend/app/apps/expo-app
pnpm test && pnpm typecheck && pnpm lint

Manual backend checks:

curl http://localhost:8000/
curl http://localhost:8000/api/health
curl http://localhost:8000/api/metrics/summary

Manual SMS ingress check:

curl -X POST http://localhost:8000/api/sms/ingress ^
  -H "Content-Type: application/json" ^
  -d "{\"sender\":\"+9779812345678\",\"body\":\"SMS-M-tudr4et3f9-X9K2Q1\"}"

PowerShell:

Invoke-RestMethod `
  -Method Post `
  -Uri http://localhost:8000/api/sms/ingress `
  -ContentType "application/json" `
  -Body '{"sender":"+9779812345678","body":"SMS-M-tudr4et3f9-X9K2Q1"}'

There is no complete backend test suite yet; test_main.http holds only scratch requests (including a stale /hello/User request the app doesn't implement).


Current Caveats & Cleanup Items

  • Both Bachao and Bachau spellings appear across names, scripts, and package metadata.
  • Root npm frontend scripts don't match the current frontend folder layout.
  • docker-compose.yml references a missing frontend/Dockerfile.dev.
  • The backend database URL is hardcoded in backend/core/database.py.
  • Dashboard routes are currently unauthenticated.
  • Dev OTPs are hardcoded: 123456 (registration step 1) and 1234 (login).
  • Some frontend API constants reference endpoints not yet implemented (/sms/decode, /sms/emergency, /sos/{id}, /guardians/{id}).
  • packages/sms-core/spec.md says only SOS is required, while the app uses SMS and the decoder accepts both.
  • Runtime artifacts are present in the checkout even though .gitignore excludes them.
  • No migration system yet β€” tables are created on startup via SQLAlchemy create_all.

Production Readiness Checklist

  • Replace hardcoded OTP checks with a real OTP provider
  • Use a strong SECRET_KEY and rotate it safely
  • Move database configuration fully into environment-driven settings
  • Add migrations (Alembic or similar)
  • Protect dashboard routes with proper admin authentication
  • Replace in-memory rate limiting and metrics with shared infrastructure
  • Restrict CORS origins
  • Store uploads in durable object storage or a managed volume
  • Add request auditing for admin actions
  • Add automated backend tests (registration, login, incident creation, guardian approval/response, SMS decoding)
  • Align frontend API constants with the backend API surface
  • Remove generated/runtime files from source control

Bachao Β· Built to reach help when the network can't. πŸ†˜

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors