# Ujjain Simhastha Mahakumbh 2028 — Website Registration

Next.js visitor registration for **Simhastha Mahakumbh** in Ujjain
(**1 April – 15 June 2028**, Shipra river).

## Quick start

```bash
cd web
cp .env.example .env.local   # then fill DB credentials (quote passwords that contain #)
npm install
npm run db:init
npm run db:init-security
npm run dev
```

Open [http://localhost:3000](http://localhost:3000) (or the port shown in the terminal).

## Environment

| Variable | Purpose |
| --- | --- |
| `DB_HOST` / `DB_PORT` / `DB_USER` / `DB_PASSWORD` / `DB_NAME` | MySQL (`ujjain_khumbh`) |
| `JWT_SECRET` | Signs OTP session tokens; also used as pass-crypto fallback in non-prod |
| `AADHAAR_PEPPER` | HMAC pepper for Aadhaar hashing (preferred over `JWT_SECRET`) |
| `PASS_ENCRYPTION_KEY` | AES-256-GCM key for `qr_payload` (64-char hex = 32 bytes, or any utf8 string) |
| `NEXT_PUBLIC_SITE_URL` | Pass / QR public links |
| `OTP_DEV_MODE=true` | Returns `dev_otp` in API responses for local testing |

**Important:** If the DB password contains `#`, wrap it in quotes in `.env.local`:

```env
DB_PASSWORD="5ph4$#%BW1QWEyu"
```

Example crypto keys (change for production):

```env
AADHAAR_PEPPER=kumbh-aadhaar-pepper-change-me
PASS_ENCRYPTION_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
```

## Pages

| Path | Description |
| --- | --- |
| `/` | Landing with full-bleed Kumbh imagery |
| `/register` | Multi-step wizard (consent → Aadhaar → mobile → OTP → profile → visit → review) |
| `/pass/[passNo]` | Digital pass + QR (print-friendly) |
| `/privacy` | Aadhaar / data notice |

## APIs (`/api/v1/registration`)

- `POST /aadhaar/validate`
- `POST /otp/send`
- `POST /otp/verify`
- `POST /visitors` (Bearer OTP session token)
- `GET /pass/:passNo`
- `GET /pass/:passNo/qr`

**Visit window:** arrival dates must be **1 April 2028 – 15 June 2028** (inclusive). Other dates are rejected.

Registration APIs enforce IP blocklist checks, in-memory rate limits (30 req / 10 min per IP), and best-effort `http_request_events` logging. Human-check rejects also write `security_events`.

Admin panel lives in the separate `../admin` application (port 3002).

## Test Aadhaar (checksum-valid)

Use a Verhoeff-valid 12-digit number, for example:

- `234567890124`
- `999999990019`

With `OTP_DEV_MODE=true`, the OTP is shown on the registration screen after send.

## Notes

- Aadhaar is stored as HMAC-SHA256 (`AADHAAR_PEPPER`) + last 4 digits — never plaintext.
- Pass QR payloads are AES-256-GCM sealed at rest (`v1:iv:ciphertext:tag`); legacy plaintext JSON still opens for older rows.
- Use `safeLog` / `safeError` on sensitive paths — production redacts Aadhaar-like numbers and OTPs.
- SMS / WhatsApp are stubbed as server logs until a gateway is connected.
- Channel is always persisted as `website`.
- Security / network tables:

```bash
npm run db:init-security
```

Creates `security_events`, `http_request_events`, `network_blocklist`, and seeds `rate_limit_policies` for OTP/registration paths.
- Location master data (cities + PIN codes) can be loaded with:

```bash
npm run db:import-locations
```

Sources: `../docs/Indian Cities Database.csv` and `../docs/pincode-india.csv`.
Registration uses PIN lookup and city autocomplete for faster home-address fill.
