# BOSS VPN Mobile Auth API

Документ для iPhone и Android приложения, которое должно:
- создать ссылку на авторизацию;
- открыть сайт для входа через Telegram или Google;
- получить session token после успешного входа;
- сразу получить subscription link и HAPP deep link.

## Базовый URL

Локально:

```text
http://localhost:6760
```

Продакшн:

```text
https://YOUR_DOMAIN
```

## Общая схема

1. Приложение вызывает `POST /api/app-auth/init`
2. Сервер возвращает `appCode` и `authUrl`
3. Приложение открывает `authUrl` во встроенном браузере или системном браузере
4. Пользователь входит на сайте через Telegram или Google
5. Сайт после входа вызывает `POST /api/app-auth/confirm`
6. Приложение опрашивает `GET /api/app-auth/check/:code`
7. После подтверждения сервер возвращает:
   - `session token`
   - `telegramId` внутреннего аккаунта
   - `connect.subUrl`
   - `connect.happLink`

Если подписки ещё нет, `connect` будет `null`.

## Авторизация в API

После получения сессии все защищённые запросы идут так:

```http
Authorization: Bearer <session_token>
```

TTL веб/мобильной сессии:
- 30 дней

## Web auth для пользователя

На сайте ручного логина больше нет.

Доступные способы входа:
- Telegram OAuth
- Google OAuth

Особенности:
- при входе через Google сервер получает подтверждённый email и записывает его в `web_users.email`
- при входе через Telegram, если email ещё не заполнен, сайт попросит его один раз
- пароль для сайта больше не требуется

## Endpoint: `POST /api/app-auth/init`

Создаёт короткий код и ссылку для входа.

Response:

```json
{
  "appCode": "9f62c3d8c9d1b1d3d2d80e7d",
  "expiresAt": "2026-07-09T12:00:00.000Z",
  "authUrl": "https://YOUR_DOMAIN/auth?appCode=9f62c3d8c9d1b1d3d2d80e7d"
}
```

Примечания:
- `appCode` живёт 10 минут
- `authUrl` нужно просто открыть пользователю

## Endpoint: `GET /api/app-auth/check/:code`

Проверка статуса авторизации.

### Пока пользователь не вошёл

```json
{
  "status": "pending"
}
```

### Если код истёк

```json
{
  "status": "expired"
}
```

### После успешного входа

```json
{
  "status": "confirmed",
  "token": "session_token_here",
  "telegramId": 8000000000001,
  "connect": {
    "subUrl": "https://YOUR_DOMAIN/sub/abc123token",
    "happLink": "happ://add/https%3A%2F%2FYOUR_DOMAIN%2Fsub%2Fabc123token"
  }
}
```

Примечания:
- `telegramId` может быть обычным Telegram ID
- для аккаунтов, созданных через Google без Telegram, сервер создаёт внутренний ID в той же модели данных
- `connect` может быть `null`, если подписка ещё не активирована

## Endpoint: `GET /api/auth/me`

Требует `Authorization: Bearer <token>`.

Возвращает профиль, баланс, подписку и устройства.

Полезные поля:
- `email`
- `displayName`
- `authProvider`
- `needsProfileCompletion`
- `sub`
- `devices`

Пример:

```json
{
  "telegramId": 8000000000001,
  "name": "Alex",
  "username": "alex@example.com",
  "email": "alex@example.com",
  "displayName": "Alex",
  "authProvider": "google",
  "hasEmail": true,
  "needsProfileCompletion": false,
  "missingProfileFields": [],
  "balance": 0,
  "discount": 0,
  "trialUsed": false,
  "sub": null,
  "pricing": {
    "extraGb": 4,
    "bypassExtraGb": 1.75
  },
  "subToken": null,
  "devices": []
}
```

## Endpoint: `GET /api/connect`

Требует `Authorization: Bearer <token>`.

Если подписка активна, возвращает:

```json
{
  "subUrl": "https://YOUR_DOMAIN/sub/abc123token",
  "happLink": "happ://add/https%3A%2F%2FYOUR_DOMAIN%2Fsub%2Fabc123token"
}
```

Если подписки нет:
- HTTP `403`
- `{ "error": "Нет активной подписки" }`

## Endpoint: `GET /api/connect/configs`

Требует `Authorization: Bearer <token>`.

Нужен, если приложение хочет не только subscription link, но и список устройств/конфигов.

Возвращает:
- `subscription`
- `connect`
- `configs[]`

## Endpoint: `POST /api/auth/logout`

Сбрасывает текущую сессию.

Response:

```json
{
  "ok": true
}
```

## Рекомендуемый mobile flow

### Вариант A. Первый вход

1. `POST /api/app-auth/init`
2. Открыть `authUrl`
3. Пользователь входит через Telegram или Google
4. Поллить `GET /api/app-auth/check/:code` каждые 2-3 секунды
5. На `confirmed` сохранить `token`
6. Если `connect != null`, предложить кнопку:
   - "Открыть в HAPP"
   - или "Скопировать ссылку подписки"
7. Если `connect == null`, показать экран выбора тарифа

### Вариант B. Повторный запуск приложения

1. Хранить `session_token` в secure storage
2. Проверять `GET /api/auth/me`
3. Если `401`, заново запускать flow через `app-auth/init`

## Обработка ошибок

Рекомендуемая логика:
- `401` -> токен истёк или недействителен, нужно переавторизоваться
- `403` на `/api/connect` -> нет активной подписки
- `403` с `code=PROFILE_INCOMPLETE` -> для Telegram-входа пользователь ещё не указал email на сайте
- `expired` в `/api/app-auth/check/:code` -> создать новый `appCode`

## Что показывать в приложении

После `confirmed` приложение уже может строить UX из этих данных:
- `token` -> для всех дальнейших API вызовов
- `connect.subUrl` -> ссылка подписки
- `connect.happLink` -> deep link для HAPP
- `sub` из `/api/auth/me` -> статус подписки и лимиты
- `devices` из `/api/auth/me` или `/api/connect/configs` -> список устройств

## Коротко

Минимальный набор для мобильного клиента:
- `POST /api/app-auth/init`
- `GET /api/app-auth/check/:code`
- `GET /api/auth/me`
- `GET /api/connect`
- `POST /api/auth/logout`
