webhooks
Webhooks Architecture: Why so complex?
Эта система вебхуков спроектирована не просто для уведомлений ("что-то случилось"), а для двусторонней интеграции с AI-агентами.
Обычные вебхуки (fire-and-forget) хороши для Slack-уведомлений, но плохи для автоматического редактирования контента. Мы строим систему, где агенты могут читать, править и коммитить изменения безопасно и эффективно.
Ключевые отличия от "обычных" вебхуков
| Фича | Зачем нужна (The "Why") |
|---|---|
| Синхронный ответ | Скорость. Агент может вернуть исправления (фиксы опечаток, форматирование) прямо в ответе на вебхук. Экономит 3 лишних HTTP-запроса (Auth -> Get -> Commit) и секунды времени. |
Защита от рекурсии (depth) |
Безопасность. Если агент исправит заметку, это вызовет новый вебхук. Без защиты (max_depth) два агента могут зациклить сервер насмерть. Система сама останавливает цепочку. |
| Short API Tokens (JWT) | Security. Вместо того чтобы давать агенту "ключ от всех дверей" (Master Key), мы даем временный токен (на 1 час) с правами только на текущие заметки. Если токен украдут, ущерб минимален. |
| Подпись HMAC | Доверие. Гарантирует, что данные пришли именно от нас, а не от хакера. Стандарт индустрии (Stripe, GitHub). |
Сценарии
-
AI-Линтер (Sync):
- Пользователь сохраняет пост.
- Вебхук летит к Линтеру.
- Линтер находит ошибку и сразу в ответе возвращает исправленный текст.
- Сервер применяет правку.
- Пользователь доволен: "Оно само исправилось!"
-
Генератор дайджестов (Cron + Async):
- Раз в сутки Cron Webhook будит Агента-Журналиста.
- Агент получает токен с доступом
read_patterns: ["blog/*"]. - Агент не спеша читает посты, пишет саммари и пушит новый пост
blog/digest.md.
Ещё сценарии
-
Индексатор (Change + Chain):
- Линтер (max_depth1) правит пост, пушит с depth1.
- Индексатор (max_depth=2) видит правку линтера, обновляет поисковый индекс.
- Линтер НЕ видит правку индексатора (depth2 > max_depth=1). Цепочка остановлена.
-
Модератор (Change + Event Filter):
- Webhook с
on_create: true,on_update: false,on_remove: false. - Срабатывает только на новые заметки. Проверяет содержимое, помечает или скрывает нежелательное.
- Webhook с
-
Бэкап (Cron + Async):
- Раз в неделю Cron Webhook будит Бэкап-агента.
- Агент получает токен с
read_patterns: ["*"],write_patterns: [](read-only). - Читает все заметки через API, экспортирует в S3/Git.
Ключевые решения
| Решение | Почему |
|---|---|
next_run_at обновляется атомарно с delivery |
Предотвращает дубликаты при крэше между enqueue и update |
TTL shortapitoken = max(timeout_seconds, appconfig TTL) |
Токен не истечёт раньше таймаута |
ON DELETE CASCADE убрать из delivery таблиц |
Soft delete (disabled_at) делает cascade бесполезным. Cleanup cron чистит deliveries |
response_schema — серверная константа |
Не хранится в БД, сервер включает в payload при отправке |
| Delivery cleanup: 30 дней | webhook_delivery_logs — 7 дней, deliveries — 30 дней, job_statuses — 30 дней |
HTTP клиент: fasthttp.Client |
Проект уже на fasthttp. DoTimeout + AcquireRequest/ReleaseRequest |
| HTTPS не форсируется, но рекомендуется | HTTP допустим для localhost/dev. Документировать риск для production |
Batch rollback при expected_hash mismatch |
Атомарность: все изменения агента применяются или не применяются. Агент получает previous_error при retry |
Тестирование
| Уровень | Инструмент | Что покрывает |
|---|---|---|
| Unit | Go + fasthttputil.InMemoryListener |
HMAC, shortapitoken, agent response parsing, write access, delivery job, depth |
| E2E | Playwright request API (e2e/webhooks.spec.js) |
Full flow: pushNotes → webhook fires → verify payload/HMAC → agent response → changes applied |
E2E тесты используют debug endpoints (/debug/test_webhook, /debug/wait_all_jobs) и pushNotes через GraphQL (не obsidian-sync CLI). HMAC верификация через Node.js crypto.createHmac.
Подробности: shared_webhooks.md → раздел "Тестирование".
Почему свои debug endpoints, а не готовые решения
Рассматривали request-baskets и webhook-tester, но отказались:
- Нет ARM-образов — request-baskets только linux/amd64, а dev-среда на ARM.
- Мало звезд на github — оба в плачевном состоянии, без активной поддержки.
- Избыточная зависимость — свои endpoints это десяток строк кода, полный контроль над поведением (статус-коды, задержки, кастомные ответы), никаких проблем с совместимостью.
Документация
Подробные технические спецификации:
- Change Webhooks — триггеры на изменение заметок (create/update/remove).
- Cron Webhooks — запуск агентов по расписанию.
- Shared Infrastructure — общие механизмы: Auth (Short Tokens), HMAC подпись, формат ответов, Retry, Debugging, Тестирование.
- Job Statuses — единый UI для отслеживания всех фоновых задач.