Skip to content

HiteshGhanchi/TechRace_2k26

Repository files navigation

TechRace 2026 — Master README

TechRace is a geo-location-based scavenger hunt with two Flutter apps (Participant, Volunteer/Admin), a Node.js/Express backend in TypeScript, and Firebase for Auth + data. This README serves as an educational guide, operational runbook, and technical setup reference.

System Architecture

  • Core Stack
    • Frontend: Flutter (GetX, Flavors for Participant vs Volunteer)
    • Backend: Node.js/Express + TypeScript
    • Firebase: Auth, Firestore (Cold Data), Realtime Database (Hot Data)
  • Docker Strategy
    • Dev: docker-compose with volume mounts and local env loading
    • Prod: Multi-stage Dockerfile (Builder → Runner) with Railway environment variables
  • Hybrid Database
    • Firestore: Clue text, hints, image URLs (cold, cost-optimized)
    • RTDB: Coordinates, team scores/state (hot, low-latency)
    • Meter Checks read only lat/long from RTDB for speed
flowchart LR
  subgraph Mobile
    P[Participant App]:::app
    V[Volunteer/Admin App]:::app
  end

  P -->|JWT + HTTPS| B[Backend API<br/>Node/Express]:::svc
  V -->|JWT + HTTPS| B

  B -->|Auth| A[Firebase Auth]:::fb
  B -->|Cold Data| F[(Firestore<br/>clues, hints, urls)]:::fb
  B -->|Hot Data| R[(Realtime DB<br/>coords, team state/scores)]:::fb

  classDef app fill:#77c,stroke:#333,color:#fff
  classDef svc fill:#6b8,stroke:#333,color:#fff
  classDef fb fill:#f9a,stroke:#333,color:#333
Loading

Why Separate Hot/Cold Data

  • Latency: Meter checks and leaderboard rely on rapid reads/writes; RTDB suits bursty, low-bandwidth polling.
  • Cost: Content (text/hints/images) changes rarely; Firestore’s document model is cheaper to store and read infrequently.
  • Simplicity: Coordinates in RTDB enable straight-line distance checks without fetching large documents.

References:

  • Dev Compose: docker-compose.yml
  • Dev Dockerfile: Dockerfile.dev
  • Prod Dockerfile: Dockerfile
  • Firebase Admin bootstrap: firebase.ts
  • Hybrid clue write: gameController:addClue
  • Meter read from RTDB: getMeterReading
graph TD
  F[(Firestore)]:::fb -->|read once per clue| APP[Apps via Backend]:::svc
  R[(RTDB)]:::fb -->|meter polling & leaderboard| APP
  subgraph Data Split
    COLD[Cold: clue text, hints, media URLs]
    HOT[Hot: lat/long, team state, scores]
  end
  COLD --> F
  HOT --> R
  classDef fb fill:#f9a,stroke:#333,color:#333
  classDef svc fill:#6b8,stroke:#333,color:#fff
Loading

Developer Guide

  • Prerequisites

    • Flutter SDK
    • Node.js v20+
    • Firebase CLI (npm i -g firebase-tools)
  • Backend (Local Dev with Docker)

    • Enter backend: cd techrace_backend
    • Copy env: duplicate .env.example to .env and fill keys
    • Compose up: docker compose up --build
      • Volumes mount ./ for hot reloading; runs npm run dev
      • Reads .env via compose env_file
    • Entrypoints and routes:
      • App: app.ts
      • Auth: authRoutes.ts
      • Game: gameRoutes.ts
      • Admin: adminRoutes.ts
  • Backend (Production)

    • Multi-stage build produces slim image
    • Secrets: .env is ignored in build via .dockerignore; use Railway variables
    • Deploy: GitHub Actions → Railway (manual or on push)
      • Workflow: deploy_backend.yml
  • Flutter App Setup

    • Enter app: cd techrace
    • Configure Firebase: flutterfire configure (generates lib/firebase_options.dart)
    • Install deps: flutter pub get
    • Run flavors:
      • Participant: flutter run --flavor participant -t lib/main_participant.dart (main_participant.dart)
      • Volunteer/Admin: flutter run --flavor volunteer -t lib/main_volunteer.dart (main_volunteer.dart)
  • Build APKs (Local)

    • Participant: flutter build apk --flavor participant -t lib/main_participant.dart
    • Volunteer: flutter build apk --flavor volunteer -t lib/main_volunteer.dart

Event Day Runbook

  • Pre-Event: Bulk Load via Python

    • Location: python_scripts
    • Requirements: pip install pandas requests
    • Upload Teams: python upload_teams.py (upload_teams.py)
      • Reads teams.csv, logs in as Admin (/api/admin/login), posts to /api/user/add-user (userController)
    • Upload Clues: python upload_clues.py (upload_clues.py)
      • Reads clues.csv, posts to /api/game/add-clue to write cold (Firestore) + hot (RTDB) (addClue)
    • Configuration Source
      • Default scripts read BASE_URL + admin creds inline; for robustness prefer env variables on the machine running uploads
  • During Event: Monitoring & Validation

    • Firebase Console
      • RTDB nodes to watch: teams/* (state, balance, last_lat/last_lng), clues/* (lat/long), base_url
    • Admin/Volunteer App
      • Login fetches base_url from RTDB and uses backend APIs (volunteer_auth_controller.dart)
      • Leaderboard pulls via backend and listens to teams (desk_controller.dart)
    • Clue Validation
      • Validators confirm team proximity to target using backend (validateTeam)
  • Emergency: Force Logout

    • Current API: POST /api/auth/logout updates Firestore is_logged_in=false and optional last lat/lng (authController)
    • Recommended: Admin-protected endpoint /api/admin/force-logout to avoid unauthenticated logout attempts

Security & Anti-Cheat

  • Meter Check Performance

    • Reads only lat/long from RTDB for fast, lightweight distance computation (getMeterReading)
    • Backend throttles writes unless movement > 10m to reduce noisy updates
  • Anti-Cheat Logic

    • Login gate checks large instantaneous movement vs last known point and denies suspicious jumps (loginTeam)
    • Soft Session Lock: JWT valid for 24h; admins can log out teams if devices fail
  • Firebase Rules (Policy)

    • Participants should not read clues/* in RTDB directly; only backend does
    • Participants may read limited team state under teams/{tid} necessary for UX
    • Admin roles can read/write administrative nodes: base_url, last_clue, validations
    • Firestore access for clue content should be backend-only

CI/CD

  • Backend Deploy
    • GitHub Actions: deploy_backend.yml pushes to Railway
    • Railway token stored as GitHub Secret RAILWAY_TOKEN
  • Mobile Build & Release
    • Local builds for Participant and Volunteer flavors with flutter build apk --flavor ...
    • Optional CI: add a workflow_dispatch-based job to build and upload signed artifacts per flavor

Future Improvements & Known Vulnerabilities

  • Align Speed Logic
    • Current: distance jump threshold at login
    • Improve: compute speed = distance / time between last_seen and now; deny >20 m/s consistently
  • Secure Logout
    • Current: /api/auth/logout is unauthenticated
    • Improve: require JWT tied to the team, and add admin-only /api/admin/force-logout
  • RTDB base_url Hardening
    • Risk: if base_url is modified by an attacker, Volunteers could be redirected
    • Improve: restrict RTDB write to admins only; validate HTTPS + whitelist domains
  • Firebase Rules
    • Enforce backend-only access to Firestore clues; block participant reads of RTDB clues/*
    • Rate-limit writes to teams/* to reduce spam updates
  • Admin Password Rotation
    • Current: rotation on each login can break ongoing scripted uploads
    • Improve: rotate on schedule or via explicit action; scripts read creds from env or service account
  • Secrets Hygiene
    • Ensure google-services.json is not committed or that API keys have strict usage restrictions
  • Server-Side Distance & Clue Access
    • Move all distance computation and clue access to backend; clients only display results
  • Observability
    • Add structured logs and dashboards for meter rates, validation errors, bans, freezes

Appendix: Quick References

  • Backend Dev Compose: docker-compose.yml
  • Dockerfiles: Dockerfile.dev, Dockerfile
  • Firebase Admin init: firebase.ts
  • Key Controllers: authController.ts, gameController.ts, adminController.ts
  • Flutter Flavor Entrypoints: main_participant.dart, main_volunteer.dart

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors