# Домены и зеркала

> Чат работает на любом вашем домене, сообщает о каждом новом сайте и позволяет заблокировать чужой сайт или оставить чат только на доменах из списка.

Зеркала меняются чаще, чем кто-то заходит в настройки. Поэтому по умолчанию чат работает на любом
домене. Когда он появляется на новом сайте, вы получаете уведомление. Чужой сайт можно
заблокировать одной кнопкой.

## Уведомление о каждом новом сайте
Когда чат впервые загружается на сайте, бот пишет в Telegram-группу вашей компании, в общую тему:
«чат появился на brand38.shop». Под сообщением — кнопка «Заблокировать».

- Нажать её может только владелец или администратор компании, остальным бот так и ответит. После нажатия в
  уведомлении видно, кто заблокировал сайт, и появляется кнопка «Разблокировать».
- О каждом сайте бот сообщает только один раз.
- О компьютере разработчика и внутренней сети (`localhost`, `*.local`, `192.168.*` и подобных)
  бот не сообщает.
- Если чат загружался на сайте до подключения группы, сайт есть в списке в приложении, но
  уведомления о нём не будет.

## Список доменов
Все сайты, где загружался чат, видны в приложении: раздел проекта «Установка», блок «Домены». Для
каждого сайта видно:

- когда чат там видели впервые и в последний раз;
- сколько разговоров там началось;
- метку «Новый» в первые 7 дней.

| Состояние | Что значит |
|---|---|
| «Работает» | Чат там работает. Сайта нет в вашем списке. |
| «Разрешён» | Сайт есть в вашем списке. Чат там работает, в том числе в строгом режиме. |
| «Не разрешён» | Включён строгий режим, и он не пускает чат на сайт. |
| «Заблокирован» | Вы заблокировали сайт. Чата там нет. |
| «Не виден N дней» | Чат последний раз видели на этом сайте, и больше 7 дней его там нет. Возможно, код убрали с сайта (красная точка). |

Владельцы и администраторы могут нажать «Заблокировать», «Разблокировать» и «Разрешить». «Разрешить» добавляет
домен сайта в список и снимает блокировку.

Без строгого режима «Разрешить» ничего не меняет для чата. Кнопка только подтверждает, что домен
ваш. Это нужно для [правила доменов](https://tolkly.io/docs/ru/knowledge.md#domain-rule): правило считает такой домен
зеркалом или отдельным сайтом. Правило включает строка «Читать новые домены» внизу блока. Когда
оно включено, кнопка «Разрешить» появляется и в уведомлении о новом сайте в Telegram.

Операторы видят список, но без кнопок. Проект хранит до 50 сайтов. Новые сайты сверх этого не
записываются, и уведомлений о них нет.

## Что получает заблокированный сайт
Ничего: ни кнопки чата, ни подсказки, ни сообщений в консоли браузера. Если на странице чат был
открыт до блокировки, отправить из него больше ничего нельзя. Поэтому заблокированный сайт не
тратит ваш лимит. Блокировка из приложения или из Telegram действует сразу.

## Строгий режим
Строгий режим нужен, если чат должен показываться только на ваших доменах. Откройте «Установка» ›
«Дополнительно», блок «Строгий режим». Включите «Только разрешённые домены» и заполните
«Разрешённые домены и маски», по одному в строке. Маска покрывает домен целиком, а не его
часть:

| Строка | Подходит | Не подходит |
|---|---|---|
| `brand.com` | `brand.com` | `www.brand.com`, `brand.com.evil.io` |
| `*.brand.com` | `www.brand.com`, `pay.brand.com` | `brand.com` |
| `brand*.shop` | `brand.shop`, `brand38.shop` | `brand38.evil.shop` |

В строгом режиме на сайте не из списка чата нет. В группу приходит сообщение «попытка с
незнакомого домена» с кнопками «Разрешить» и «Заблокировать».

Пока зеркала часто меняются, держите строгий режим выключенным. Если режим включён, а список пуст,
чат не работает нигде.

## Ключ для скрипта смены зеркал
Если сайт переводит на новое зеркало скрипт, он может сам добавить новый домен в список. Для этого
нужен ключ: в «Установка» › «Дополнительно», в блоке «Ключ для скрипта смены зеркал», нажмите
«Выпустить ключ». Ключ показывается один раз. «Выпустить новый ключ» сразу отключает старый.
Передайте ключ разработчику: хранить его нужно на сервере, никогда на странице.

Пример для разработчика. Адрес есть в этом блоке, в «Пример: добавить зеркало в список»:

```sh
KEY=tk_domains_…
API=https://api.tolkly.io/v1/projects/<project>/origins

# Что сейчас в списке
curl -H "Authorization: Bearer $KEY" $API

# Добавить новое зеркало, убрать старое; остальное остаётся
curl -X POST $API -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
  -d '{"add": ["brand39.shop"], "remove": ["brand38.shop"]}'

# Заменить весь список; "strict" необязателен и переключает режим
curl -X PUT $API -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
  -d '{"patterns": ["brand.com", "*.brand.com", "brand\\d+\\.shop"], "strict": true}'
```
Список важен даже без строгого режима: по нему чат понимает, какие домены ваши, когда строит
ссылки на источники (ниже).

### Поручить ИИ-агенту
Под ключом у владельцев и администраторов есть кнопка «Поручить ИИ-агенту». Она даёт промпт, с уже подставленным
проектом, для агента, который правит ваш скрипт смены зеркал (Claude Code, Cursor). По этому
промпту агент:

- добавляет новый домен до того, как туда отправят посетителей;
- хранит ключ в переменной окружения `TOLKLY_DOMAINS_KEY` на сервере, никогда в репозитории или
  на странице;
- проверяет, что домен отмечен «Разрешён».

Здесь в промпте вместо идентификатора проекта стоит `your-project`. Скопировать промпт: «Открыть
в…» › «Промпт для ИИ-агента».

```text
Сделай так, чтобы смена зеркала этого сайта сама добавляла новый домен в список разрешённых доменов чата Tolkly, и чат продолжал работать в строгом режиме.

Проект: your-project
API доменов: https://api.tolkly.io/v1/projects/your-project/origins
Ключ: переменная окружения TOLKLY_DOMAINS_KEY на сервере, где идёт смена зеркала. Владелец выпускает его в Tolkly: «Установка» › «Дополнительно» › «Ключ для скрипта смены зеркал».

1. Прочитай https://tolkly.io/docs/en/domains.md, разделы о строгом режиме и о ключе скрипта зеркал. Если страница не открывается, хватит этого промпта.
2. Найди скрипт или задачу, которая переводит сайт на новый домен-зеркало: шаг деплоя, смена DNS или CDN, задача по расписанию, которая регистрирует домены. Если такой нет, остановись и скажи мне.
3. В нём, до того как DNS или редирект отправят посетителей на новый домен, добавь домен в список: POST https://api.tolkly.io/v1/projects/your-project/origins с заголовками "Authorization: Bearer $TOLKLY_DOMAINS_KEY" и "Content-Type: application/json" и телом {"add": ["<новый домен>"]}. Домен — только хост (brand39.casino), без схемы и пути. В строгом режиме домен не из списка остаётся без чата, поэтому этот запрос идёт первым.
4. Можно в том же запросе убрать старое зеркало: {"add": ["<новый домен>"], "remove": ["<старый домен>"]}. PUT не используй, пока я не попрошу: он заменяет весь список.
5. Неудачный запрос — это неудачный шаг смены зеркала: на 429 и 5xx повтори; на 401 (ключа нет или владелец выпустил новый) и на 400 (в ответе указана запись, которую не приняли) остановись и сообщи. В лог пиши статус, но не ключ.
6. Ключ читай только из TOLKLY_DOMAINS_KEY: никогда не клади его в репозиторий, страницу, код для браузера или лог. API не отдаёт заголовков CORS, поэтому из браузера его не вызывают. Если переменная не задана там, где работает скрипт, остановись и попроси меня её задать.
7. Проверь: GET https://api.tolkly.io/v1/projects/your-project/origins с тем же заголовком Authorization отвечает {"strict": …, "patterns": […]}, и новый домен есть среди patterns. Когда чат загрузится на этом домене, в Tolkly в «Установка» › «Домены» он будет отмечен «Разрешён». Потом перечисли изменённые файлы.
```

## Посетитель на новом зеркале
- **Ссылки на источники идут за посетителем.** Если ссылка в ответе ведёт на другой ваш домен, она
  открывается на сайте, с которого пишет посетитель. На `brand38.shop` ссылка
  `https://brand.com/rules` становится `https://brand38.shop/rules`: основной домен у посетителя
  может быть заблокирован. Ваши домены — это проиндексированный сайт, домены из вашего списка и
  сайты, где работал чат и которые никто не заблокировал.
- **Вошедший посетитель сохраняет разговор.** Браузер хранит разговор отдельно для каждого сайта,
  поэтому на новом зеркале анонимный посетитель начинает новый. Если ваш сайт подписывает
  посетителя, тот получит свой последний открытый разговор на любом зеркале. Настройка для
  разработчика: [Подпись посетителя](https://tolkly.io/docs/ru/identity.md).
