pelagia-portal/EpfoService
Hardik 1ef0c53ff0
All checks were successful
PR checks / checks (pull_request) Successful in 45s
PR checks / integration (pull_request) Successful in 30s
test(crewing): cover EPFO stub contract + /api/epfo permission gate
- Extract EpfoService's pure stub + validation logic into a dependency-free
  module (EpfoService/src/stub.ts); index.ts now uses it in its stub branches so
  the tested logic IS the production stub behaviour.
- epfo.test.ts (App integration): the deterministic stub contract
  (OTP 000000 → matched, UAN/OTP validation, session expiry) and the Next proxy
  routes' verify_bank_epf gate — 401 unauthenticated, 403 for the MPO, Accounts
  passes through to a mocked upstream, body validated before the upstream call.
  No EPFO_LIVE, no running service.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:56:14 +05:30
..
src test(crewing): cover EPFO stub contract + /api/epfo permission gate 2026-06-22 23:56:14 +05:30
package.json feat(crewing): EPFO/UAN assisted verification (GstService pattern, flagged) 2026-06-22 22:43:24 +05:30
README.md feat(crewing): EPFO/UAN assisted verification (GstService pattern, flagged) 2026-06-22 22:43:24 +05:30
tsconfig.json feat(crewing): EPFO/UAN assisted verification (GstService pattern, flagged) 2026-06-22 22:43:24 +05:30

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).