# Route Spec

## Route ID
`users-followers-list`

## Endpoint
`GET /api/v1/users/{userId}/followers`

## Human Description
Returns paginated followers for a user. Supports local list search via query `q`. Each item carries the display name and whether the viewer already follows that user, so clients can render a followers list with per-row Follow/Following buttons without extra profile fetches.

## Authentication
- Required: `yes`

## Request
### Path Parameters
- `userId` (`string`, required)

### Query Parameters
- `q` (`string`, optional): search within this list.
- `cursor` (`string`, optional)
- `limit` (`number`, optional, default `20`, max `100`)

## Responses
### Success: `200 OK`
```json
{
  "success": true,
  "message": "Followers loaded",
  "data": {
    "items": [
      {
        "id": "usr_9",
        "username": "ahmed",
        "fullName": "Ahmed Said",
        "profilePhotoUrl": null,
        "viewerFollows": false
      }
    ],
    "nextCursor": "cur_2"
  }
}
```

Notes:
- `viewerFollows` reflects whether the authenticated viewer follows the listed user; it is `false` for anonymous requests and for the viewer's own row.

### Error: `401 Unauthorized`
When returned:
- Missing or invalid access token.

Body:
```json
{
  "success": false,
  "error": {"code": "UNAUTHORIZED", "message": "Authentication required.", "details": {}}
}
```

### Error: `404 Not Found`
When returned:
- User does not exist.

Body:
```json
{
  "success": false,
  "error": {"code": "USER_NOT_FOUND", "message": "User does not exist.", "details": {}}
}
```

## Data & Caching Dependencies
- **Spanner Tables:** `user_follows, users (Read)`
- **Redis Cache:** `None`
- **GCS Storage:** `None`
- **Edge Cache (CDN):** `No`

## Side Effects
- None (read-only endpoint).
