Контракт серверной сводки и доставки уведомлений
Назначение
Функция public.broker_lead_notification_summary(uuid) формирует ограниченный текст заявки для Telegram-уведомления или внутреннего CRM-канала.
Она не отправляет сообщение самостоятельно, не хранит Telegram-токен и не выполняет HTTP-запросы. Вызов выполняется только серверным кодом после сохранения заявки.
Атомарный захват и завершение доставки выполняют:
public.claim_broker_lead_notification(uuid, text);public.complete_broker_lead_notification(uuid, text, boolean, text).
Миграции
Применяются последовательно:
202607070001_create_broker_leads.sql;202607130002_broker_leads_v2.sql;202607130003_broker_lead_preparation.sql;202607130004_broker_lead_notification_summary.sql;202607130005_broker_lead_notification_delivery.sql.
До применения всех миграций lead_capture.endpoint остаётся пустым, рабочий режим сайта — web3forms.
Доступ
Все три RPC используют security definer, фиксированный search_path = public и доступны только service_role.
Права:
public— запрещено;anon— запрещено;authenticated— запрещено;service_role— разрешён вызов.
Функции не должны вызываться из браузера и не должны становиться публичными RPC.
Источник данных
Сводка строится только из строки public.broker_leads, уже сохранённой серверным обработчиком.
Используются:
- request ID;
- имя и телефон;
- город и способ связи;
- ипотечный сценарий;
- объект, стоимость, взнос и доход;
- технический приоритет;
- страница-источник;
- очищенные поля подготовки.
Исходный raw_payload напрямую в уведомление не вставляется.
Контекст подготовки
Раздел ПОДГОТОВКА ДО ОБРАЩЕНИЯ добавляется только при наличии хотя бы одного значения:
journey_type;journey_stage;journey_scenario_slug;preparation_completed;remaining_questions.
Отметки берутся из очищенного JSON-массива preparation_completed. Используется не более четырёх значений, прошедших whitelist в trigger sync_broker_lead_preparation.
Эта информация не означает вероятность банковского одобрения и не заменяет проверку брокером.
Статусы доставки
Используются значения:
disabled— Telegram secrets не настроены;pending— заявка ожидает захвата обработчиком;sending— одна Edge Function получила атомарное право отправки;sent— Telegram подтвердил HTTP-ответ и результат зафиксирован;failed— попытка завершилась ошибкой и автоматически не повторяется.
Дополнительные поля:
notification_attempt_count;notification_attempted_at;notification_sent_at;notification_last_error.
В notification_last_error сохраняется только короткий безопасный код без токена, chat ID и stack trace.
Атомарный захват
claim_broker_lead_notification переводит в sending только:
pending;sending, который остаётся незавершённым более 15 минут.
Одновременные запросы не получают два успешных claim. Статусы sent, failed и disabled автоматически повторно не захватываются.
Повтор с тем же request_id может восстановить незавершённое pending или зависшее sending, но не создаёт вторую заявку.
Завершение
complete_broker_lead_notification меняет только текущий sending:
- на
sentпри успехе; - на
failedпри ошибке.
Создаётся событие notification_sent или notification_failed. Ошибка уведомления не удаляет сохранённую заявку и не меняет её CRM-статус.
Остаточный аварийный риск
Telegram API не поддерживает идемпотентный ключ отправки. Если Telegram уже принял сообщение, но Edge Function аварийно завершилась до вызова complete_broker_lead_notification, запись останется в sending. После 15 минут повторный запрос может восстановить доставку и отправить сообщение ещё раз.
Поэтому:
- request ID всегда включается в текст;
- дубликат легко определяется по одному ID;
- автоматическое восстановление выполняется только после 15 минут;
failedне повторяется автоматически;- включение Telegram требует отдельного smoke-теста аварийного окна.
Это компромисс между риском потери уведомления и абсолютным запретом повторной доставки.
Обработка ошибок
При неизвестном UUID функция сводки завершает вызов ошибкой broker_lead_not_found.
Серверный канал должен:
- не раскрывать внутреннюю ошибку клиенту сайта;
- не считать ошибку уведомления ошибкой сохранения заявки;
- переводить захваченную попытку в
failed; - создавать техническое событие без полного payload;
- не записывать Telegram secrets в базу или логи.
Telegram
Telegram-токен и chat ID хранятся только в secrets Edge Function.
После активации Supabase обработчик:
- сохраняет заявку;
- атомарно вызывает
claim_broker_lead_notification; - получает текст через
broker_lead_notification_summary; - отправляет текст в подтверждённый чат;
- вызывает
complete_broker_lead_notification; - записывает событие результата.
Прямое включение Telegram до проверки пяти миграций, получателя, срока хранения и smoke-теста запрещено.