# EpfoService EPFO / UAN **assisted-lookup** proxy for PPMS crewing — mirrors `GstService`. Drives the EPFO member portal headlessly (Playwright) to fetch a member record for a UAN, so Accounts can confirm a crew member's EPF details against the source. ## Why it differs from GstService - The GST portal has an anonymous **captcha** lookup. The EPFO member portal does not — "Know your UAN" is gated by an **OTP to the member's registered mobile**. So the handshake is two steps (`/otp` then `/verify`). - **Aadhaar is out of scope.** UIDAI restricts Aadhaar verification to licensed AUA/KUA via consented e-KYC; it cannot be portal-scraped. PPMS keeps Aadhaar **assisted-manual** (stores only the last 4 digits, masked). ## Endpoints | Method | Path | Body | Returns | |---|---|---|---| | GET | `/health` | — | `{ status, mode, sessionCount }` | | POST | `/otp` | `{ uan }` | `{ sessionId, mobileHint }` | | POST | `/verify` | `{ sessionId, uan, otp }` | `{ matched, name, status }` | ## Modes - **Stub (default):** `EPFO_LIVE` unset/`false`. Deterministic responses — OTP `000000` → matched member, anything else → not matched. Lets the app integration run end-to-end in dev/CI without the live portal. - **Live:** `EPFO_LIVE=true`. Drives the real portal. **The page selectors and the OTP/captcha flow are marked `TODO(live)` and must be validated against a real session before enabling** — the portal layout is the source of truth. ## Env ``` PORT=3004 SESSION_TTL_MS=300000 EPFO_LIVE=false EPFO_PORTAL_URL=https://unifiedportal-mem.epfindia.gov.in/memberinterface/ ``` ## Run ``` pnpm install pnpm dev # tsx watch # or pnpm build && pnpm start ``` The PPMS app reaches it via `EPFO_SERVICE_URL` (proxied through `/api/epfo`).