# AGNET Uzbekistan Platform — Project Specifications & Plan

**Repository:** `agnet-uzbekistan-platform` (Next.js BFF + farmer UI)  
**Version:** 0.1.0 (pilot)  
**Last updated:** 2026-06-26  
**Related backend:** `../mpgis-farmer-platform` (NestJS core-api, PostgreSQL/PostGIS, Prisma)  
**Wizard field spec:** [`WIZARD_FIELD_SPEC.md`](./WIZARD_FIELD_SPEC.md) (UX Research — comprehensive per-step fields)

---

## Executive Summary

AGNET is a farmer financial inclusion platform for Uzbekistan. This repository delivers the public marketing site, OTP-based farmer authentication, a 13-step onboarding wizard, and a post-onboarding dashboard with four modules (Finance, Trade, Identity, Inputs). The Next.js app acts as a BFF proxy to the NestJS `core-api` backend.

**OpenAPI specifications:**

| Spec | Path | Scope |
|------|------|-------|
| BFF API (this repo) | `specs/openapi/bff-api.v1.yaml` | Browser-facing `/api/*` routes |
| Core API | `../mpgis-farmer-platform/packages/api-contracts/openapi/core-api.v1.yaml` | Auth, onboarding, parcels, cases |
| GIS | `gis.v1.yaml` | Parcel geometry, NDVI enrichment |
| Scoring | `scoring.v1.yaml` | ML/rules fusion scoring |
| Documents | `documents.v1.yaml` | Presigned upload, OCR extraction |
| Rules | `rules.v1.yaml` | Eligibility rules engine |

---

## System Architecture

```mermaid
flowchart TB
    subgraph Browser
        UI[Next.js Pages]
        Client[lib/api-client.ts]
    end

    subgraph Agnet_BFF["Agnet BFF (this repo)"]
        API["/api/* routes"]
        Mock[dev-api-mock.ts]
        MW[middleware.ts]
    end

    subgraph Backend["mpgis-farmer-platform"]
        Core[core-api :4000]
        GIS[gis-service]
        Score[scoring-service]
        Docs[documents-service]
        DB[(PostgreSQL + PostGIS)]
    end

    UI --> Client
    Client --> API
    MW --> UI
    API -->|CORE_API_URL| Core
    API -->|CORE_API_USE_MOCK| Mock
    Core --> DB
    Core --> GIS
    Core --> Score
    Core --> Docs
```

---

## Completed Actions (Phase 0–2)

### Infrastructure & Dev Experience

| # | Item | Status | Evidence |
|---|------|--------|----------|
| 1 | Next.js 15 App Router scaffold | ✅ Done | `app/`, `package.json` |
| 2 | Full dev stack script (PostGIS + Prisma + core-api + Next) | ✅ Done | `scripts/start-dev.sh`, `npm run dev:stack` |
| 3 | Environment configuration template | ✅ Done | `.env.local.example` |
| 4 | In-memory dev API mock | ✅ Done | `lib/dev-api-mock.ts`, `CORE_API_USE_MOCK` |
| 5 | Upstream proxy layer | ✅ Done | `lib/proxy-upstream.ts` |
| 6 | Design system tokens | ✅ Done | `design-system/agnet-global/MASTER.md` |

### Authentication

| # | Item | Status | Evidence |
|---|------|--------|----------|
| 7 | OTP request endpoint (`POST /api/auth/otp`) | ✅ Done | `app/api/auth/[...path]/route.ts` |
| 8 | OTP verify with httpOnly cookie | ✅ Done | Sets `agnet_token`, strips `accessToken` from response |
| 9 | Session introspection (`GET /api/auth/me`) | ✅ Done | Returns user + activeSession |
| 10 | Logout (`POST /api/auth/logout`) | ✅ Done | Clears cookie locally |
| 11 | Apply page (`/farmers/apply`) | ✅ Done | `app/farmers/apply/page.tsx` |
| 12 | Login page (`/farmers/login`) | ✅ Done | `app/farmers/login/page.tsx` |
| 13 | Auth middleware for protected routes | ✅ Done | `middleware.ts` |
| 14 | Farmer routing logic | ✅ Done | `lib/farmer-routing.ts` |

### Onboarding Wizard (13 Steps)

| Step | Key | Component | API Integration | Status |
|------|-----|-----------|-----------------|--------|
| 1 | ACCOUNT | `StepAccount.tsx` | PATCH step | ✅ Done |
| 2 | CONSENT | `StepConsent.tsx` | PATCH + reference options | ✅ Done |
| 3 | KYC | `StepKyc.tsx` | PATCH (pilot simplified) | ✅ Done |
| 4 | FARM_PROFILE | `StepFarmProfile.tsx` | PATCH + districts | ✅ Done |
| 5 | LAND_SKETCH | `StepLandSketch.tsx` | PATCH | ✅ Done |
| 6 | GIS_MAPPING | `StepGisMapping.tsx` | PATCH (coords or agent_pending) | ✅ Done |
| 7 | CROP_PLAN | `StepCropPlan.tsx` | PATCH + crops reference | ✅ Done |
| 8 | FARM_ASSETS | `StepFarmAssets.tsx` | PATCH + asset_types | ✅ Done |
| 9 | FINANCE_REQUEST | `StepFinanceRequest.tsx` | PATCH + finance_purposes | ✅ Done |
| 10 | DOCUMENTS | `StepDocuments.tsx` | Upload API + PATCH | ✅ Done |
| 11 | REVIEW | `StepReview.tsx` | PATCH + submit | ✅ Done |
| 12 | SCORING | `StepScoring.tsx` | Poll `/status` | ✅ Done |
| 13 | RESULT | `StepResult.tsx` | PATCH + redirect | ✅ Done |

**Supporting onboarding infrastructure:**

| # | Item | Status |
|---|------|--------|
| 15 | Onboarding wizard shell + step navigation | ✅ Done — `OnboardingWizard.tsx` |
| 16 | Session hook (`useOnboardingSession`) | ✅ Done |
| 17 | Reference options hook | ✅ Done — `useReferenceOptions` |
| 18 | Create/resume session API | ✅ Done — `POST /api/onboarding` |
| 19 | Step update API | ✅ Done — `PATCH /api/onboarding/{id}/steps/{step}` |
| 20 | Submit for scoring | ✅ Done — `POST /api/onboarding/{id}/submit` |
| 21 | Scoring status polling | ✅ Done — `GET /api/onboarding/{id}/status` |
| 22 | Document upload (multipart) | ✅ Done — `POST /api/documents/upload` |
| 23 | Draft save per step | ✅ Done — `onSaveDraft` callbacks |

### Farmer Dashboard

| # | Item | Status | Evidence |
|---|------|--------|----------|
| 24 | Dashboard hub page | ✅ Done | `app/farmers/dashboard/page.tsx` |
| 25 | Finance module page | ✅ Done | `app/farmers/dashboard/finance/page.tsx` |
| 26 | Trade module page | ✅ Done | `app/farmers/dashboard/trade/page.tsx` |
| 27 | Identity module page | ✅ Done | `app/farmers/dashboard/identity/page.tsx` |
| 28 | Inputs module page | ✅ Done | `app/farmers/dashboard/inputs/page.tsx` |
| 29 | Dashboard API + view models | ✅ Done | `GET /api/farmer/dashboard`, `lib/farmer-dashboard.ts` |
| 30 | Dashboard data hook | ✅ Done | `useFarmerDashboard` |

### Marketing & Public Pages

| # | Item | Status |
|---|------|--------|
| 31 | Landing page with 3D hero | ✅ Done — `app/page.tsx` |
| 32 | Pilot program page | ✅ Done — `app/pilot/page.tsx` |
| 33 | Partner inquiry page (UI) | ✅ Done — `app/partner/page.tsx` |
| 34 | SEO (sitemap, robots) | ✅ Done — `app/sitemap.ts`, `app/robots.ts` |

### Testing

| # | Item | Status |
|---|------|--------|
| 35 | Playwright E2E — full onboarding wizard | ✅ Done — `e2e/tests/onboarding.spec.ts` |
| 36 | Playwright E2E — farmer dashboard | ✅ Done — `e2e/tests/farmer-dashboard.spec.ts` |
| 37 | Wizard step helpers | ✅ Done — `e2e/helpers/wizard.ts` |

### API Specifications (this deliverable)

| # | Item | Status |
|---|------|--------|
| 38 | BFF OpenAPI 3.1 spec | ✅ Done — `specs/openapi/bff-api.v1.yaml` |
| 39 | Shared enums + step payloads | ✅ Done — `specs/openapi/components/` |
| 40 | Project plan document | ✅ Done — this file |
| 41 | Wizard field specification (UX Research) | ✅ Done — `specs/WIZARD_FIELD_SPEC.md` |

---

## Wizard Field Gap Analysis (Pilot vs Target)

Current pilot collects **~35 fields** across 13 steps. UX Research recommends **~120 fields** tiered P0/P1/P2 for scoring accuracy, institution compliance, and platform features.

| Step | Pilot fields (today) | P0 target | P1 additions | Key gaps |
|------|---------------------|-----------|--------------|----------|
| ACCOUNT | 2 | 4 | +3 | `verificationMethod`, language preference, referral |
| CONSENT | 4 | 8 | +3 | Granular consents (credit, GIS, institution sharing) |
| KYC | 4 | 8 | +5 | OneID enrichment, PINFL, official name/DOB prefill |
| FARM_PROFILE | 8 | 10 | +6 | `region`, `farmerType`, cascading district, co-applicant |
| LAND_SKETCH | 6 | 8/parcel | +5 | Multi-parcel array, `landUseType`, lease details |
| GIS_MAPPING | 4 | 6 | +5 | `parcelId` link, GPS accuracy, polygon GeoJSON |
| CROP_PLAN | 4/crop | 4/crop | +6 | `areaHa` per crop, market intent, buyer contract |
| FARM_ASSETS | 4/asset | 5/asset | +6 | `quantity`, `totalAssetValue`, storage, ownership |
| FINANCE_REQUEST | 5 | 7 | +8 | UZS amounts, `termMonths`, expenses, use-of-funds |
| DOCUMENTS | 3 | 6+ | +4 | Quality score, institution-specific docs, assist mode |
| REVIEW | 2 | 3 | +4 | Conflict detection, attestation, OCR override tracking |
| SCORING | 4 | 4 | +4 | Plain-language reason mapping, enrichment display |
| RESULT | 2 | 4 | +4 | FinanceCase ref, conditional requirements, module CTAs |

**Critical UX change:** Reorder steps so **DOCUMENTS (10) runs before FINANCE_REQUEST (9)** — enables OCR prefill of income/loans and reduces farmer effort (~2 min saved, higher DTI accuracy).

**Time budget:** Pilot 28–42 min → P0 comprehensive **35–50 min** (acceptable with prefill) → P0+P1 **50–70 min** (requires usability validation).

---

## To-Do List (Prioritized Backlog)

### P0 — Production Blockers

| ID | Task | Owner | Depends On | Acceptance Criteria |
|----|------|-------|------------|---------------------|
| T-001 | Integrate OneID eKYC in StepKyc | Backend + Frontend | OneID sandbox credentials | Real identity verification; remove pilot bypass |
| T-002 | Wire partner inquiry form to CRM/API | Frontend + Backend | Lead capture endpoint | Form submission persists; confirmation email |
| T-003 | Remove document upload stub fallback | Backend | S3/presign pipeline live | No `stubDocumentUpload` in production path |
| T-004 | Align core-api OpenAPI with implementation | Backend | — | Add `/auth/me`, `/farmer/dashboard`, `/reference/options` to `core-api.v1.yaml` |
| T-005 | Production SMS/OTP provider | Backend | Twilio/local UZ provider | OTP delivered in prod; dev OTP removed |
| T-006 | Environment secrets management | DevOps | — | `JWT_SECRET`, DB creds in vault; no `.env` in prod |

### P1 — Quality & Maintainability

| ID | Task | Owner | Depends On | Acceptance Criteria |
|----|------|-------|------------|---------------------|
| T-007 | Replace `any` types in `api-client.ts` | Frontend | BFF OpenAPI spec | Generated or hand-written TypeScript types |
| T-008 | OpenAPI spec validation in CI | DevOps | T-038 | `swagger-parser` passes on PR |
| T-009 | Contract tests (BFF ↔ core-api) | QA | T-004 | Pact or schema tests for proxy routes |
| T-010 | Unit tests for `farmer-routing.ts`, `mapDashboardResponse` | Frontend | — | >90% branch coverage |
| T-011 | Root README with setup instructions | Docs | — | `npm run dev:stack` documented |
| T-012 | API documentation portal (Swagger UI / Redoc) | DevOps | T-038 | `/docs` or external portal |

### P2 — Feature Enhancements

| ID | Task | Owner | Depends On | Acceptance Criteria |
|----|------|-------|------------|---------------------|
| T-013 | Real-time GIS map picker in StepGisMapping | Frontend + GIS | `gis.v1.yaml` endpoints | Draw polygon on map; save GeoJSON |
| T-014 | Document OCR prefill in finance step | Backend | documents-service OCR | Auto-fill from uploaded bank/tax docs |
| T-015 | Multi-language UI (uz/ru/en) | Frontend | i18n framework | All onboarding steps translated |
| T-016 | Farmer PWA / offline draft save | Frontend | `NEXT_PUBLIC_FARMER_PWA_URL` | Service worker; resume offline drafts |
| T-017 | Re-application flow for completed users | Frontend + Backend | — | Clear UX when user returns after completion |
| T-018 | Admin/officer portal (separate app) | Backend | core-api admin routes | Review cases, override scoring |
| T-019 | Notification templates (SMS/email) | Backend | NotificationTemplate model | Status updates on case progress |
| T-020 | Institution checklist integration | Frontend | `/institutions/{id}/checklist` | Dynamic required docs per institution |

### P3 — Scale & Operations

| ID | Task | Owner | Depends On | Acceptance Criteria |
|----|------|-------|------------|---------------------|
| T-021 | Rate limiting on OTP endpoints | Backend | — | 429 after N requests per phone/IP |
| T-022 | Distributed tracing (X-Correlation-Id) | Full stack | — | Correlation ID propagated BFF → core-api |
| T-023 | Error envelope standardization | Full stack | — | BFF returns same shape as core-api errors |
| T-024 | Performance benchmarks | QA | — | Lighthouse >90; wizard step <2s load |
| T-025 | Accessibility audit (WCAG 2.1 AA) | QA | — | axe-core passes on all farmer flows |
| T-026 | Multi-country expansion scaffold | Backend | CountryProfile model | Second country profile configurable |

### Wizard Field Expansion (UX Research)

Full field definitions: [`WIZARD_FIELD_SPEC.md`](./WIZARD_FIELD_SPEC.md)

#### W-P0 — Launch data quality (must have for scoring & compliance)

| ID | Task | Steps | Owner | Depends On | Acceptance Criteria |
|----|------|-------|-------|------------|---------------------|
| W-001 | Extend OpenAPI `onboarding-steps.yaml` with P0 comprehensive fields | All | Frontend + Backend | — | All P0 fields in spec match UI + API schemas |
| W-002 | Add `regions` reference data + cascading region→district picker | 4, 5 | Frontend + Backend | Reference seed | District filters by selected region |
| W-003 | OneID redirect flow + KYC→FARM_PROFILE prefill chain | 3, 4 | Frontend + Backend | T-001 | Official name/DOB/gender prefilled; override shows warning |
| W-004 | Implement StepFarmProfile P0 fields (`region`, `farmerType`) | 4 | Frontend | W-002 | All P0 profile fields saved to `stepData.FARM_PROFILE` |
| W-005 | **Reorder wizard:** DOCUMENTS before FINANCE_REQUEST | 9, 10 | Frontend | — | Step order updated; E2E tests pass; OCR runs before finance |
| W-006 | UZS-primary finance fields + FX snapshot (`amountUzs`, `monthlyIncomeUzs`) | 9 | Frontend + Backend | — | Amounts stored in UZS; USD computed with dated FX rate |
| W-007 | Granular consent checkboxes (credit_bureau, gis_satellite, data_sharing) | 2 | Frontend + Backend | Consent CMS | Separate required consents; stored in `ConsentRecord` |
| W-008 | Land parcel P0 expansion (`landUseType`, `isPrimary`, parcel array shell) | 5 | Frontend + Backend | W-002 | Single parcel uses array model; ready for multi-parcel |
| W-009 | GIS step: link `parcelId`, capture GPS `accuracyM` | 6 | Frontend | W-008 | Primary parcel linked; accuracy stored when available |
| W-010 | Crop `areaHa` per entry + sum validation vs total land | 5, 7 | Frontend | W-008 | Warning if crop areas exceed declared land |
| W-011 | Finance P0: add `termMonths`, repayment capacity in UZS | 9 | Frontend | W-006 | Term chips (6/12/24/36); all amounts in UZS |
| W-012 | Plain-language reason code mapping (scoring + result UI) | 12, 13 | Frontend | — | Top 3 reasons shown in farmer-friendly language |
| W-013 | Review attestation text + grouped summary cards with edit links | 11 | Frontend | W-001 | Six summary groups; legal attestation from CMS |
| W-014 | Result step: show `financeCaseId`, conditional requirements list | 13 | Frontend + Backend | FinanceCase API | Case reference displayed; conditional actions listed |
| W-015 | Uzbek/Russian labels for all P0 wizard fields | All | Frontend + Content | W-001 | uz/ru strings for every P0 label and error message |

#### W-P1 — High-value enrichment (score accuracy & institution approval)

| ID | Task | Steps | Owner | Depends On | Acceptance Criteria |
|----|------|-------|-------|------------|---------------------|
| W-016 | Multi-parcel land model (add/remove parcels, backend `LandParcel` sync) | 5, 6 | Full stack | W-008 | 2+ parcels persist; each linkable in GIS/crops |
| W-017 | Map polygon draw (GeoJSON) with area cross-check | 6 | Frontend + GIS | T-013, W-009 | Polygon saved; mismatch >20% flagged |
| W-018 | OCR prefill pipeline with confidence badge on finance fields | 9, 10 | Full stack | T-014, W-005 | Income/loans prefilled; farmer confirms or overrides |
| W-019 | Review conflict detection engine (income vs OCR, area vs crops) | 11 | Backend + Frontend | W-010, W-018 | Conflicts surfaced; resolution required before submit |
| W-020 | Institution-dynamic document checklist | 10 | Frontend + Backend | T-020 | Required docs change per selected institution |
| W-021 | Crop P1 fields (`intendedMarket`, `hasBuyerContract`, `priorYearYield`) | 7 | Frontend | W-010 | Market intent drives trade matching seed |
| W-022 | Asset P1 fields (ownership, title proof, storage capacity) | 8 | Frontend | — | Collateral metadata captured |
| W-023 | Finance P1 (`monthlyExpensesUzs`, `useOfFundsBreakdown`, `expectedRevenueUzs`) | 9 | Frontend | W-006, W-018 | DTI uses net income; revenue cross-check vs crops |
| W-024 | Agent-assist mode flags (KYC, GIS, documents) + officer handoff | 3, 6, 10 | Frontend + Backend | T-044 | `agent_pending` / `agent_assisted` routes to ops queue |
| W-025 | Input/buyer recommendation seeding on RESULT step | 13 | Backend + Frontend | Scoring pipeline | Top 3 inputs + buyer matches shown post-score |
| W-026 | Audio prompts for consent text and field labels (uz/ru) | 2, All | Frontend | W-015 | Tap-to-hear on consent and key fields |
| W-027 | Icon-based selects for low-literacy paths | 4, 7, 8, 9 | Frontend | W-015 | Gender, crop, asset, purpose as icon cards |

#### W-P2 — Nice to have (defer post-launch)

| ID | Task | Steps | Notes |
|----|------|-------|-------|
| W-028 | Co-applicant / guarantor financial fields | 4, 9 | Joint liability products |
| W-029 | Livestock secondary production section | 7 | Diversification score |
| W-030 | Asset photo uploads linked to collateral | 8, 10 | `FarmAsset.photoKeys` |
| W-031 | Application experience rating on RESULT | 13 | Emoji 1–5 scale |
| W-032 | WhatsApp opt-in and referral source on ACCOUNT | 1 | Growth analytics |

---

## Detailed Project Plan

### Phase 0 — Discovery & Foundation ✅ COMPLETE

**Duration:** Weeks 1–2  
**Goal:** Establish monorepo structure, design system, and dev environment.

| Milestone | Deliverables | Status |
|-----------|--------------|--------|
| M0.1 | Tech stack selection (Next.js 15, NestJS, PostGIS) | ✅ |
| M0.2 | Design system tokens | ✅ |
| M0.3 | Dev stack orchestration script | ✅ |
| M0.4 | Prisma schema (27 models in backend) | ✅ |

---

### Phase 1 — Auth & Onboarding Core ✅ COMPLETE

**Duration:** Weeks 3–6  
**Goal:** End-to-end farmer signup through onboarding wizard.

| Milestone | Deliverables | Status |
|-----------|--------------|--------|
| M1.1 | OTP auth flow (apply + login) | ✅ |
| M1.2 | Cookie-based session management | ✅ |
| M1.3 | Onboarding session CRUD | ✅ |
| M1.4 | Steps 1–6 (Account → GIS) | ✅ |
| M1.5 | Steps 7–13 (Crop → Result) | ✅ |
| M1.6 | Document upload | ✅ |
| M1.7 | Scoring status polling | ✅ |
| M1.8 | E2E wizard test | ✅ |

---

### Phase 2 — Dashboard & Marketing ✅ COMPLETE

**Duration:** Weeks 7–8  
**Goal:** Post-onboarding experience and public presence.

| Milestone | Deliverables | Status |
|-----------|--------------|--------|
| M2.1 | Dashboard hub + 4 modules | ✅ |
| M2.2 | Dashboard API aggregation | ✅ |
| M2.3 | Landing + pilot + partner pages | ✅ |
| M2.4 | Middleware route protection | ✅ |
| M2.5 | E2E dashboard test | ✅ |

---

### Phase 3 — Production Hardening 🔄 IN PROGRESS

**Duration:** Weeks 9–12  
**Goal:** Replace pilot shortcuts with production integrations.

| Milestone | Deliverables | Tasks | Status |
|-----------|--------------|-------|--------|
| M3.1 | API contract completeness | T-004, T-038, T-008 | 🔄 Specs created; CI pending |
| M3.2 | Identity verification | T-001 | ⏳ Pilot bypass active |
| M3.3 | Document pipeline | T-003, T-014 | ⏳ Stub fallback exists |
| M3.4 | Type safety | T-007, T-010 | ⏳ Widespread `any` |
| M3.5 | Partner lead capture | T-002 | ⏳ UI-only form |
| M3.6 | Production OTP/SMS | T-005, T-006 | ⏳ Dev OTP `1234` |
| M3.7 | Wizard P0 field expansion | W-001–W-015 | ⏳ Pilot minimal fields only |
| M3.8 | Wizard step reorder (docs before finance) | W-005 | ⏳ Finance before documents today |

**Exit criteria:** No mock/stub paths in production; all P0 tasks closed; wizard P0 fields (W-001–W-015) implemented.

**Estimated effort — Wizard P0:** ~25 dev-days (frontend 15d, backend 8d, content/i18n 2d)

---

### Phase 4 — GIS & Scoring Integration ⏳ PLANNED

**Duration:** Weeks 13–16  
**Goal:** Real geospatial enrichment and ML scoring.

| Milestone | Deliverables | Tasks |
|-----------|--------------|-------|
| M4.1 | Interactive GIS map | T-013 |
| M4.2 | NDVI/SATAI enrichment pipeline | Backend scoring service |
| M4.3 | Reason code transparency | Already in `/status`; enhance UI |
| M4.4 | Institution case routing | FinanceCase → institution adapters |
| M4.5 | Wizard P1 enrichment | W-016–W-027 |
| M4.6 | Multi-parcel + polygon GIS | W-016, W-017, T-013 |

**Dependencies:** `gis.v1.yaml`, `scoring.v1.yaml` services deployed.

---

### Phase 5 — Localization & PWA ⏳ PLANNED

**Duration:** Weeks 17–20  
**Goal:** Uzbek/Russian language support and mobile-first experience.

| Milestone | Deliverables | Tasks |
|-----------|--------------|-------|
| M5.1 | i18n framework | T-015 |
| M5.2 | Farmer PWA | T-016 |
| M5.3 | Offline draft persistence | T-016 |
| M5.4 | Accessibility compliance | T-025, W-027 |
| M5.5 | Wizard i18n complete | W-015, W-026 |

---

### Phase 6 — Operations & Scale ⏳ PLANNED

**Duration:** Weeks 21–24  
**Goal:** Production operations, admin tools, multi-country readiness.

| Milestone | Deliverables | Tasks |
|-----------|--------------|-------|
| M6.1 | Admin/officer portal | T-018 |
| M6.2 | Notification system | T-019 |
| M6.3 | Observability (tracing, metrics) | T-022 |
| M6.4 | Rate limiting & security hardening | T-021 |
| M6.5 | Second country profile | T-026 |

---

## API Surface Summary

### BFF Routes (documented in `bff-api.v1.yaml`)

```
POST   /api/auth/otp
POST   /api/auth/verify          → sets agnet_token cookie
GET    /api/auth/me
POST   /api/auth/logout

POST   /api/onboarding           ?forceNew=true
GET    /api/onboarding/{id}
DELETE /api/onboarding/{id}
PATCH  /api/onboarding/{id}/steps/{step}
POST   /api/onboarding/{id}/submit
GET    /api/onboarding/{id}/status

POST   /api/documents/upload     multipart/form-data

GET    /api/farmer/dashboard

GET    /api/reference/options    ?countryCode=UZ&type=districts
```

### Frontend Pages

```
/                           Marketing landing
/pilot                      Pilot program
/partner                    Partner inquiry (no API)
/farmers/apply              New farmer OTP signup
/farmers/login              Returning farmer login
/farmers/onboarding         13-step wizard
/farmers/dashboard          Dashboard hub
/farmers/dashboard/finance
/farmers/dashboard/trade
/farmers/dashboard/identity
/farmers/dashboard/inputs
```

---

## Environment Variables

| Variable | Required | Default | Purpose |
|----------|----------|---------|---------|
| `NEXT_PUBLIC_SITE_URL` | No | `https://agnet.global` | Metadata, sitemap |
| `CORE_API_URL` | Yes (prod) | `http://localhost:4000` | Backend proxy target |
| `CORE_API_USE_MOCK` | No | `false` | Enable in-memory mock |
| `MPGIS_BACKEND_ROOT` | No | — | Path for `dev:stack` |
| `DATABASE_URL` | Dev stack | — | PostGIS connection (backend) |
| `JWT_SECRET` | Dev stack | — | Backend JWT signing |

---

## Verification Checklist

Use this checklist to validate spec accuracy against the running system:

- [ ] `POST /api/auth/otp` with valid phone returns `{ sent: true }`
- [ ] `POST /api/auth/verify` with code `1234` (dev) sets cookie and returns `{ user }`
- [ ] `GET /api/auth/me` with cookie returns user + `activeSession`
- [ ] `POST /api/onboarding` creates session at step `ACCOUNT`
- [ ] `PATCH /api/onboarding/{id}/steps/CONSENT` advances to `KYC`
- [ ] `POST /api/documents/upload` accepts PDF under 10 MB
- [ ] `POST /api/onboarding/{id}/submit` transitions to `submitted`
- [ ] `GET /api/onboarding/{id}/status` returns score + reasonCodes after scoring
- [ ] `GET /api/farmer/dashboard` returns four modules after completion
- [ ] `GET /api/reference/options?type=districts` returns array without auth
- [ ] `npm run test:e2e:wizard` passes
- [ ] `npm run test:e2e` (dashboard spec) passes

---

## Risk Register

| Risk | Impact | Likelihood | Mitigation |
|------|--------|------------|------------|
| Pilot KYC bypass in production | High | Medium | T-001; gate deploy on OneID integration |
| Document stub in prod | High | Medium | T-003; health check rejects stub path |
| BFF/core-api spec drift | Medium | High | T-004, T-008, T-009 contract tests |
| OTP abuse / cost | Medium | Medium | T-021 rate limiting |
| Type unsafety causes runtime errors | Medium | High | T-007 generated types from OpenAPI |
| Wizard too long → dropout | High | Medium | W-005 step reorder, OCR prefill, KYC prefill; cap P0 at ≤50 min |
| Duplicate data entry frustration | Medium | High | W-003 KYC prefill, W-018 OCR prefill, W-019 conflict resolution |
| Crop area vs land mismatch | Medium | Medium | W-010 validation before submit |
| Missing region hierarchy | Low | High | W-002 cascading picker |

---

## Next Immediate Actions (Sprint 1)

1. **W-001** — Extend OpenAPI step schemas with P0 comprehensive fields (2 days)
2. **W-005** — Reorder DOCUMENTS before FINANCE_REQUEST + update E2E (1 day)
3. **W-002** — Add regions reference + cascading district picker (2 days)
4. **W-006** — UZS-primary finance fields (2 days)
5. **T-011** — Add root `README.md` with `dev:stack` setup (1 day)
6. **T-008** — Add OpenAPI validation to CI (1 day)
7. **T-004** — PR to backend adding missing endpoints to `core-api.v1.yaml` (2 days)

**Sprint 2 (Wizard P0 continuation):** W-003, W-004, W-007, W-008, W-009, W-010, W-011, W-012, W-013, W-014, W-015

---

*This document is the single source of truth for project status, API contracts, and roadmap. Update task statuses as work completes.*
