# Telegram Authentication and Bot Operations

## Trust boundary

The browser sends the unchanged value of `Telegram.WebApp.initData` to `POST /api/v1/auth/telegram/exchange`. The server does not accept `initDataUnsafe`, a client user object, a client timestamp, or a referral identity as proof.

The verifier:

1. Parses a bounded query string and rejects duplicate protected fields.
2. Builds the alphabetically sorted data-check string without `hash`.
3. Derives the secret key with HMAC-SHA-256 using `WebAppData` and the bot token.
4. Compares the expected and received hashes in constant time.
5. Rejects stale or future `auth_date` values.
6. Validates the Telegram user object and converts its safe integer ID to a decimal string.

Only after all checks pass does one MySQL transaction synchronize the user, create the user's referral code, record a valid first-touch referral, and create the session.

## Browser exchange

```http
POST /api/v1/auth/telegram/exchange
Content-Type: application/json

{"init_data":"<unchanged Telegram.WebApp.initData>"}
```

The response sets an opaque cookie. Its raw token is never written to the database or returned in JSON. MySQL stores a SHA-256 hash, idle/absolute expiries, Telegram authentication time, normalized IP address, and a user-agent hash.

After exchange, request a session-bound CSRF pair:

```text
GET /api/v1/security/csrf
```

Send both the issued CSRF cookie and `X-CSRF-Token` header for unsafe cookie-authenticated routes such as logout. `GET /api/v1/auth/me` can be used to restore authenticated UI state.

## Referral attribution

- Direct Mini App links may include `startapp=ref_<code>`; the signed `start_param` is used.
- Bot links may send `/start ref_<code>`; the secret-authenticated webhook update is used.
- Attribution is first-touch and only applies while creating a new user.
- Missing, unknown, late, or self-referral values do not create a referral.
- Referral rewards and activation remain owned by Phase 12.

## Webhook lifecycle

Telegram must send `X-Telegram-Bot-Api-Secret-Token` matching `TELEGRAM_WEBHOOK_SECRET`. A valid update is reserved by `update_id` in MySQL before dispatch. Already processing, processed, or ignored updates receive an acknowledgement without running twice. Failed updates can be reserved again when Telegram retries.

The synchronous Phase 7 handler supports private-chat text commands. Phase 16 will move delivery and broadcast work to the queue/outbox system.

## Registration commands

Review `.env`, DNS/TLS, the configured webhook URL, and the target bot before running:

```bash
npm run verify:environment
npm run telegram:webhook:set
```

Remove the webhook while retaining pending updates:

```bash
npm run telegram:webhook:remove
```

Dropping pending Telegram updates is destructive and therefore explicit:

```bash
node bin/remove-telegram-webhook.js --drop-pending-updates
```

Command output never prints the bot token or webhook secret. Phase 7 construction did not call a live Telegram API or modify a live database.

## Security invariants

- Bot token, webhook secret, session token, and raw `initData` are not logged.
- Authentication exchange has a stricter rate-limit policy than general traffic.
- Webhook and exchange are the only CSRF exemptions; each has a Telegram-specific proof.
- Mini App URLs in bot keyboards must use HTTPS.
- User-controlled names are HTML-escaped in bot messages.
- Unknown updates and non-private commands are ignored safely.
- Business rewards, balance, and task eligibility are never accepted from Telegram messages or the browser.

## Primary references

- [Telegram Mini Apps: initialization and data validation](https://core.telegram.org/bots/webapps)
- [Telegram Bot API: webhooks and secret token header](https://core.telegram.org/bots/api)
- [Telegram Bot features: deep linking and start parameters](https://core.telegram.org/bots/features)
