# Turn 2 — NestJS Backend

## What's new in this drop

```
apps/api/
├── package.json
├── tsconfig.json
├── nest-cli.json
└── src/
    ├── main.ts                         Bootstrap: helmet, cookie-parser, CORS, validation, exception filter
    ├── app.module.ts                   Root module wiring everything
    │
    ├── common/
    │   ├── decorators/auth.decorators.ts    @Public, @RequiresCaptain, @Internal, @CurrentUser
    │   ├── filters/all-exceptions.filter.ts Centralised error response shape
    │   ├── guards/jwt-auth.guard.ts         JWT cookie guard (global)
    │   ├── guards/captain.guard.ts          Captain role enforcement
    │   ├── guards/internal.guard.ts         Cron secret guard
    │   ├── pipes/zod-validation.pipe.ts     Pipe wrapping zod schemas
    │   └── prisma/                          PrismaModule + PrismaService (global)
    │
    └── modules/
        ├── auth/         FULL: login, logout, /me, change-password
        ├── health/       FULL: /health, /health/ready
        ├── users/        FULL CRUD shape (captain only)
        ├── localities/   FULL: list (read-only)
        ├── samuday/      FULL: list + create
        ├── locations/    FULL: search, get, create-from-place-id
        ├── places/       SHELL: autocomplete + place details (Google fetch is TODO)
        ├── routes/       FULL cache logic + Google fetch TODO
        ├── vihars/       FULL: create, list, get, cancel, close-manual, reopen, whatsapp-message
        ├── allocations/  FULL: allocate, deallocate, check-in, check-out, on-behalf, approve-distance
        ├── stats/        SHELL: shape correct, real aggregations are TODO
        └── internal/     FULL: auto-close cron (every 30 min) + manual trigger endpoint
```

## What's actually wired up vs TODO

**Working end-to-end (no further code needed):**
- Login / logout / change password
- Health check
- Locality + samuday list
- Location search and dedup
- Vihar create / list / get / cancel / manual close / reopen / WhatsApp message generation
- Allocate / deallocate volunteers
- Check-in / check-out (incl captain on-behalf)
- Distance tolerance check (1 km default) and approval queue plumbing
- Auto-close cron (runs every 30 min via @nestjs/schedule)
- City-scoped multi-tenancy enforced at every controller

**Stubs labelled `TODO(claude-code)` that need real implementation on your laptop:**
- `PlacesService.autocomplete` and `fetchPlaceDetails` - Google Places API calls
- `RoutesService.fetchFromGoogle` - Google Routes API call (cache works, just the fetch is stubbed)
- `StatsService.cityStats` partial fields - top contributors, locality breakdown, daily trend, leaderboard
- `ViharsController.update` - partial update endpoint

These are intentional stubs because:
- Google API calls need real keys to test (sandbox can't reach Google)
- Stats SQL is finicky and best built incrementally with real seeded data

## How to run after pulling Turn 2

```bash
# After unzipping Turn 2 into the same vihar-sewa/ folder from Turn 1:
pnpm install
pnpm db:generate          # regenerates Prisma client
pnpm db:migrate            # if you haven't already
pnpm db:seed
pnpm dev:api               # starts NestJS on :4001

# In another terminal, smoke-test:
curl http://localhost:4001/health
curl http://localhost:4001/health/ready

# Login (returns a Set-Cookie):
curl -i -X POST http://localhost:4001/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"captain1","password":"Change@Me123"}'

# Save the cookie value, then call /api/auth/me with it.
```

## Known issues / careful spots

1. **`@nestjs/schedule` cron starts firing immediately on `pnpm dev:api`** — that's fine, but if you don't yet have data, it's a no-op. The first real run will be when `seed` has been executed and at least one in_progress vihar has aged past its window.

2. **The `Reflector` in `JwtAuthGuard` and `InternalGuard` reads metadata** — the order in `AuthModule.providers` is `Internal → JWT → Captain`. NestJS runs guards in the order they're registered. That order matters: Internal short-circuits before JWT for cron routes.

3. **Login is currently single-tenant smart but multi-tenant naive** — it looks up username globally because there's no city selector yet. For the pilot (one city) this is fine. When city #2 onboards, you'll need either a subdomain prefix or a city dropdown on the login screen. Schema is ready; only login flow needs adapting.

4. **The `_count: { select: { allocations: { where: ... } } }` filtered count** in `vihars.service.ts` — Prisma supports this but only in versions ≥ 4.3. Pinned to `^5.14.0` so we're safe.

5. **`bigint` from `audit_log.audit_id`** — Prisma returns BigInt. If you ever JSON.stringify it, you'll need a serializer. Not a Phase 1 issue but flagged for later.

## What Turn 3 will deliver (frontend)

- Next.js 14 App Router project under `apps/web/`
- Tailwind + shadcn/ui setup
- PWA manifest + service worker (next-pwa)
- Login screen (working)
- Role chooser
- Captain dashboard shell
- Volunteer dashboard shell
- Bottom nav for both roles
- API client wrapper with auth cookie handling
- Theme + base components (Button, Card, Input, etc.)

After Turn 3, feature work moves to Claude Code on the laptop. I'll provide tight task briefs for: vihar create form, allocation step, share sheet, check-in/out screens, dashboard widgets, location autocomplete UI, etc.
