<div align="center">

# 🛴 BeebBeeb

**Dockless scooter & bike sharing platform for Saudi Arabia**

Bilingual (العربية / English, full RTL) · Microservices backend · Web dashboards · Native mobile apps

</div>

---

## Table of contents

- [What is BeebBeeb](#what-is-beebbeeb)
- [Deliverables](#deliverables)
- [Architecture](#architecture)
- [Tech stack](#tech-stack)
- [Repository layout](#repository-layout)
- [Prerequisites](#prerequisites)
- [Quick start  run the whole backend](#quick-start--run-the-whole-backend)
- [Service ports & Swagger](#service-ports--swagger)
- [The core ride flow](#the-core-ride-flow)
- [Running the web apps](#running-the-web-apps)
- [Running the mobile apps](#running-the-mobile-apps)
- [Testing](#testing)
- [Configuration & secrets](#configuration--secrets)
- [Conventions](#conventions)

---

## What is BeebBeeb

BeebBeeb lets a rider open a map, find a nearby scooter or bike, scan its QR to unlock, ride and
pay by the minute from an in-app wallet, and park inside an allowed zone  no docking stations.
It also serves **investors** (own a fleet, earn a share of revenue) and **operators** (a
super-admin dashboard for fleet, zones, pricing, customers, staff and an audit trail).

Every user-facing surface is **bilingual Arabic/English with correct RTL** for Arabic.

## Deliverables

| # | Deliverable | Directory | Stack | Status |
|---|---|---|---|---|
| 1 | Backend (11 microservices) | [`backend/`](backend) | Java 17 · Spring Boot 3.4 | ✅ builds + 61 tests green |
| 2 | Super-admin dashboard | [`superadmin/`](superadmin) | Next.js 14 · TypeScript | ✅ builds + runs |
| 3 | Investor dashboard | [`investor/`](investor) | Next.js 14 · TypeScript | ✅ builds + runs |
| 4 | Marketing website | [`website/`](website) | Next.js 14 · TypeScript | ✅ builds + runs |
| 5 | Android customer app | [`AndroidApp/`](AndroidApp) | Kotlin · Jetpack Compose | ✅ builds a debug APK |
| 6 | iOS customer app | [`IosApp/`](IosApp) | Swift · SwiftUI | 📄 source (builds on a Mac) |

> The full architecture & build spec lives in [`beebbeeb-architecture.md`](beebbeeb-architecture.md).

## Architecture

Modular Spring Boot microservices, each independently deployable, communicating over **REST**
(synchronous) and **Kafka** (asynchronous events). One shared PostgreSQL uses a **schema per
service**; Redis backs geo-queries; **EMQX** (MQTT) is the only path to the physical locks.

```mermaid
flowchart LR
  subgraph Clients
    APP[Mobile apps<br/>iOS / Android]
    ADM[Super-admin<br/>Next.js]
    INV[Investor<br/>Next.js]
  end

  APP --> AUTH[auth-service]
  APP --> FLEET[fleet-service]
  APP --> BOOK[booking-service]
  APP --> WAL[user-wallet-service]
  APP --> PAY[payment-service]
  ADM --> GW[admin-gateway]
  INV --> INVS[investor-service]

  BOOK --> FLEET
  BOOK --> IOT[iot-bridge-service]
  BOOK --> WAL
  BOOK --> ZONE[zone-service]
  AUTH --> NOTIF[notification-service]

  IOT <-->|MQTT| EMQX[(EMQX)]
  EMQX <-->|lock| LOCK[[OMNI lock]]

  AUTH & FLEET & BOOK & WAL & PAY & ZONE & NOTIF & INVS & GW & CFG[config-service] --> PG[(PostgreSQL<br/>schema-per-service)]
  FLEET --> REDIS[(Redis GEO)]
  AUTH & FLEET & IOT & BOOK & WAL & PAY & NOTIF & INVS -->|events| KAFKA[(Kafka)]
```

### The 11 backend services

| Service | Responsibility |
|---|---|
| **auth-service** | Registration, phone + OTP, JWT issuance |
| **user-wallet-service** | Wallet balance, top-ups, immutable ledger |
| **fleet-service** | Scooter registry, status, battery, Redis GEO nearby-search |
| **booking-service** | Ride lifecycle: allocate → unlock → active → end → invoice |
| **zone-service** | Geofencing (green / red / slow / compound zones) |
| **iot-bridge-service** | The only service that talks to lock hardware, over MQTT/EMQX |
| **payment-service** | MyFatoorah top-ups & refunds |
| **notification-service** | SMS (Yamamah) + push (FCM/APNs) |
| **investor-service** | Revenue-split calculation, investor earnings reports |
| **admin-gateway** | Super-admin dashboard BFF, RBAC, staff & roles, audit log |
| **config-service** | Encrypted vault for 3rd-party API keys (AES-256-GCM) |

## Tech stack

- **Backend:** Java 17, Spring Boot 3.4, Spring Data JPA, Flyway, Spring Kafka, Spring Integration
  MQTT, Spring Security (OAuth2 resource server), springdoc-openapi (Swagger), Maven.
- **Data & infra:** PostgreSQL 16, Redis 7, Apache Kafka 3.8 (KRaft), EMQX 5.
- **Web:** Next.js 14 (App Router), TypeScript, Tailwind CSS.
- **Mobile:** Kotlin + Jetpack Compose (Android); Swift + SwiftUI (iOS).
- **3rd parties (behind provider ports, stubbed for offline dev):** Yamamah (SMS), MyFatoorah
  (payments), FCM/APNs (push), OMNI (locks), Keycloak (planned OAuth2).

## Repository layout

```
backend/            11 Spring Boot services + db/schemas + docker Dockerfiles
  <service>/          each: pom.xml, src/, Dockerfile
  db/schemas/         00_init_schemas.sql  schema + role per service
superadmin/         Next.js super-admin dashboard  (→ admin-gateway)
investor/           Next.js investor dashboard      (→ investor-service)
website/            Next.js marketing landing page
AndroidApp/         Kotlin/Compose customer app
IosApp/             SwiftUI customer app (XcodeGen project.yml)
assests/            brand logo
docker-compose.yml  full backend stack (infra + 11 services)
.env.example        copy to .env for docker-compose
```

## Prerequisites

| To run… | You need |
|---|---|
| Backend stack (recommended) | **Docker** + Docker Compose v2 |
| Backend services directly | JDK 17, Maven (or the bundled `mvnw`) |
| Web apps | **Node 18+** and npm |
| Android app | JDK 17 + Android SDK (or Android Studio) |
| iOS app | macOS + Xcode + XcodeGen (`brew install xcodegen`) |

## Quick start  run the whole backend

```bash
# 1. secrets / config
cp .env.example .env        # edit if you like (JWT_SECRET, CONFIG_MASTER_KEY, host ports)

# 2. bring up infrastructure only (fast  Postgres, Redis, Kafka, EMQX)
docker compose up -d postgres redis kafka emqx

# 3. …or the entire stack, building all 11 service images (slower the first time)
docker compose up -d --build

# check everything is healthy
docker compose ps

# tail logs
docker compose logs -f booking-service

# tear down (‑v also wipes the database volume)
docker compose down -v
```

On first start, `backend/db/schemas/00_init_schemas.sql` runs automatically and creates one
Postgres **schema + login role per service**; each service then applies its own **Flyway**
migrations. Services find each other by container DNS (`postgres:5432`, `kafka:9092`, `emqx:1883`,
`redis`).

## Service ports & Swagger

Every service exposes interactive **Swagger UI** and an OpenAPI document, plus a health check.

| Service | Port | Swagger UI | OpenAPI JSON | Health |
|---|---|---|---|---|
| auth-service | 8081 | http://localhost:8081/swagger-ui.html | `/v3/api-docs` | `/actuator/health` |
| fleet-service | 8082 | http://localhost:8082/swagger-ui.html | `/v3/api-docs` | `/actuator/health` |
| iot-bridge-service | 8083 | http://localhost:8083/swagger-ui.html | `/v3/api-docs` | `/actuator/health` |
| booking-service | 8084 | http://localhost:8084/swagger-ui.html | `/v3/api-docs` | `/actuator/health` |
| user-wallet-service | 8085 | http://localhost:8085/swagger-ui.html | `/v3/api-docs` | `/actuator/health` |
| payment-service | 8086 | http://localhost:8086/swagger-ui.html | `/v3/api-docs` | `/actuator/health` |
| zone-service | 8087 | http://localhost:8087/swagger-ui.html | `/v3/api-docs` | `/actuator/health` |
| notification-service | 8088 | http://localhost:8088/swagger-ui.html | `/v3/api-docs` | `/actuator/health` |
| admin-gateway | 8089 | http://localhost:8089/swagger-ui.html | `/v3/api-docs` | `/actuator/health` |
| investor-service | 8090 | http://localhost:8090/swagger-ui.html | `/v3/api-docs` | `/actuator/health` |
| config-service | 8091 | http://localhost:8091/swagger-ui.html | `/v3/api-docs` | `/actuator/health` |

Infra dashboards: **EMQX** → http://localhost:18083 (default `admin` / `public`).

## The core ride flow

The heart of the product, spanning several services and race-safe by design:

```mermaid
sequenceDiagram
  participant App
  participant Auth as auth-service
  participant Pay as payment-service
  participant Wal as wallet-service
  participant Fleet as fleet-service
  participant Book as booking-service
  participant IoT as iot-bridge
  participant Lock

  App->>Auth: register(phone) → OTP → verify → JWT
  App->>Pay: top up (package) → capture
  Pay-->>Wal: payment.captured (Kafka) → credit wallet
  App->>Fleet: nearby scooters
  App->>Book: allocate(qr)  [X-User-Id]
  Book->>Fleet: reserve (status IN_USE)
  Book->>IoT: UNLOCK command
  IoT->>Lock: MQTT downlink
  Lock-->>IoT: UNLOCKED (uplink)
  IoT-->>Book: lock.status (Kafka) → ride ACTIVE
  App->>Book: end(photo, gps)
  Book->>Fleet: release (AVAILABLE)
  Book->>Wal: debit fare
  Book-->>App: invoice
```

Key guarantees: a scooter can have **at most one live ride** (enforced by a DB partial-unique
index), unlock is **asynchronous** (allocate only dispatches the command; the ride goes ACTIVE
when the lock confirms), and every cross-service money/ride operation is **idempotent**.

## Running the web apps

Each is a standard Next.js app (Node 18+):

```bash
cd superadmin   # or investor / website
npm install
npm run dev      # http://localhost:3000
npm run build    # production build / typecheck
```

- **superadmin** talks to `admin-gateway`  set `NEXT_PUBLIC_ADMIN_API_URL` (default `:8089`).
- **investor** talks to `investor-service`  set `NEXT_PUBLIC_INVESTOR_API_URL` (default `:8090`).
- **website** is presentational (no backend).

All three share a language toggle (AR/EN with RTL) and the brand theme.

## Running the mobile apps

**Android** (`AndroidApp/`)  needs JDK 17 + Android SDK:

```bash
cd AndroidApp
./gradlew :app:assembleDebug        # builds app/build/outputs/apk/debug/app-debug.apk
```

Base URLs use `10.0.2.2` (the host as seen from the emulator).

**iOS** (`IosApp/`)  needs macOS + Xcode + XcodeGen:

```bash
cd IosApp
xcodegen generate && open BeebBeeb.xcodeproj   # then Run (⌘R)
```

See [`IosApp/README.md`](IosApp/README.md) for details.

## Testing

```bash
# a single backend service
cd backend/auth-service && mvn test

# all 11 services
cd backend && for s in */; do (cd "$s" && mvn -q test) || echo "FAILED: $s"; done

# a web app (typechecks all routes)
cd superadmin && npm run build
```

## Configuration & secrets

- Third-party keys never live in code. `config-service` stores them **AES-256-GCM encrypted**
  (master key from `CONFIG_MASTER_KEY`); the super-admin dashboard manages them.
- `docker-compose` reads `.env` (copy from `.env.example`). `JWT_SECRET` is shared by auth-service
  (signs) and admin-gateway (validates). Dev DB password is `change_me`.
- Every 3rd-party integration has an **offline stub** so the whole system runs end-to-end with no
  external accounts. Most are toggled by an env flag (`YAMAMAH_ENABLED`, `PUSH_ENABLED`,
  `MQTT_ENABLED`); **MyFatoorah is fully vault-driven**  it acts as a real client only when the
  super-admin has set `myfatoorah.apiKey` in `config-service` (no `MYFATOORAH_ENABLED` flag), and
  the Android app then takes top-ups through MyFatoorah's **native in-app card view**.

## Conventions

- **Bilingual AR/EN + RTL** on every UI surface, built in from the start.
- **Idempotency** on cross-service operations (ride debit, top-up credit, revenue split) keyed by
  a reference id + a DB unique constraint.
- **Kafka payloads are JSON strings**  services don't share classes; each side keeps its own
  contract DTO (with `ignore-unknown`) so producers can evolve freely.
- **Provider ports + stubs** for every external dependency (SMS, payments, push, locks).
- `ddl-auto: validate`  Flyway owns the schema; Hibernate validates the mapping against it.
