Linear перейшов у статус Live у каталозі інтеграцій Elido 22 травня 2026 року. Першою подією, яку ми запустили, став broken_link_hook - коли наш сканер знаходить непрацююче коротке посилання, він створює issue в Linear у команді, обраній під час підключення, з метриками кліків у тілі тікету та мітками, що маршрутизуються за тегами. Цей пост - технічний розбір для інженерів: як працює автентифікація, як виглядає JSON-payload і як ми розширили той самий пайплайн на стрибки порогу кліків, щоб черговий отримував тікет, а не дзвінок о третій ночі.
Якщо ви підтримуєте сотні або тисячі коротких посилань у продакшні, ви вже знаєте цей сценарій збою. Маркетинг змінює ціль кампанії, новий URL повертає 404, і ніхто цього не помічає - поки користувач не опублікує скриншот мертвого посилання в Bluesky. Linear - це місце, де ваша команда вже займається тріажем багів, тому саме туди ми і надсилаємо тікет.
Підключення Linear через Personal API Key
Інтеграція Linear використовує Personal API Key, а не OAuth. Ми зробили цей вибір з трьох причин: API Key обмежений робочим простором, краще переживає зміну адміністраторів порівняно з OAuth-токенами, прив'язаними до конкретного користувача, і документація API: Authentication Linear прямо рекомендує його для задач типу сервер-сервер.
Згенеруйте ключ у Linear: Налаштування, API, Personal API keys, Створити ключ. Назвіть його elido-integration, щоб пізніше можна було відкликати без здогадок. Скопіюйте ключ (починається з lin_api_) і вставте його в картку інтеграції Linear у дашборді Elido.
Що відбувається далі: ми виконуємо запит viewer для перевірки ключа, потім запит teams для заповнення селектора команди. Ви обираєте команду за замовчуванням. Цей вибір записує рядок в integration_configs у Postgres, включно з team ID, присвоєним Linear. При наявності кількох команд тегову маршрутизацію можна додати тут же - детальніше нижче.
POST /v1/workspaces/:id/integrations/linear/connect
{
"api_key": "lin_api_<redacted>",
"default_team_id": "TEAM_a1b2c3",
"default_priority": 2,
"labels": ["short-link", "auto-filed"]
}
За лаштунками сервіс api-core зберігає ключ у зашифрованому вигляді згідно зі схемою envelope-шифрування з ADR-0036. Розшифрований ключ існує в пам'яті лише під час фактичного GraphQL-виклику. Ми ніколи не логуємо сире значення; у UI логів інтеграції відображаються лише останні 4 символи.
Важлива примітка: Personal API Keys Linear прив'язані до користувача, який їх створив. Якщо цей користувач піде з компанії і ви деактивуєте його обліковий запис, ключ перестане працювати. Найкраща практика - створити в Linear сервісного користувача (ми використовуємо [email protected]) і генерувати ключ від його імені.
Подія broken_link_hook - що її запускає і що міститься в тілі
Наш сервіс url-scanner щотижня обходить усі активні короткі посилання в робочому просторі. Для кожного посилання він виконує HTTP HEAD на адресі призначення, потім GET, якщо HEAD не підтримується, а відтак перевіряє TLS-ланцюжок. Чотири умови переводять посилання в статус зламаного:
- HTTP 4xx або 5xx при двох послідовних перевірках (подвійна перевірка для фільтрації транзієнтних 500)
- TLS прострочений або самопідписаний там, де тиждень тому він був валідний
- DNS NXDOMAIN - хост призначення більше не резолвиться
- Збіг із відбитком припаркованого домену - хост резолвиться, але тіло відповіді відповідає відомому шаблону сквотера (ми підтримуємо невеликий набір відбитків)
При спрацьовуванні будь-якої з чотирьох умов сканер публікує подію link.broken у Redpanda. Webhook-dispatcher її споживає, знаходить активні інтеграції і для Linear матеріалізує наступний payload.
Реальний payload broken_link_hook зі staging-оточення (частину полів скорочено):
{
"event": "link.broken",
"link_id": "01J9V7QXMZ8K2Y3N4P5R6T7W8Z",
"short_url": "https://s.elido.me/spring-launch",
"destination_url": "https://oldcampaign.example.com/landing",
"failure_type": "http_5xx",
"failure_detail": "502 Bad Gateway, 2 consecutive probes",
"last_working_at": "2026-05-28T14:22:00Z",
"detected_at": "2026-06-04T03:11:42Z",
"clicks_last_7d": 2841,
"clicks_last_24h": 412,
"top_referrers": [
{ "host": "linkedin.com", "clicks": 1203 },
{ "host": "twitter.com", "clicks": 488 },
{ "host": "direct", "clicks": 612 }
],
"tags": ["campaign-spring-2026", "paid"],
"owner_email": "[email protected]"
}
Адаптер Linear у services/api-core/internal/integrations/linear/broken_link_hook.go бере цей payload і формує GraphQL-мутацію до Issues API Linear. Заголовок issue слідує фіксованому шаблону, щоб черговий міг знайти його через grep:
[Elido] Broken link: /spring-launch (502 Bad Gateway)
Тіло - це структурований Markdown із п'яти розділів: деталі посилання, останній робочий часовий штамп, дельта кліків відносно 7-денного baseline, три головних реферери та блок запропонованого рішення. Блок рішення дивиться на failure_type і обирає шаблонну пораду - для http_5xx: "Перевірте, чи не застосовує призначення rate limit або не знаходиться в процесі деплою"; для parked_domain: "Домен міг закінчитись або бути захоплений сквотером, заархівуйте це посилання"; і так далі.
Мітки призначаються з двох джерел: ваш набір міток за замовчуванням (налаштовується при підключенні) і динамічні мітки, похідні зі списку тегів. Якщо тег відповідає paid або organic, він додається як мітка, щоб PM-и могли фільтрувати свої представлення в Linear.
Дедуплікація, rate limits і dead-letter queue
Ми дедуплікуємо події broken_link_hook за хостом призначення на 24 години. Якщо oldcampaign.example.com впав і 800 коротких посилань ведуть на нього, ви отримаєте один тікет у Linear з усіма 800 короткими URL у тілі, а не 800 окремих тікетів. Це сувора порода з ранньої бети - перший клієнт, який потрапив на впалий домен, був засипаний тікетами.
GraphQL-ендпоінт Linear має глобальний rate limit на робочий простір. Наш webhook-dispatcher відстежує заголовок Retry-After і використовує експоненційний backoff із повним джиттером до п'яти спроб. Після п'яти спроб подія потрапляє в чергу недоставлених повідомлень. Записи DLQ видно в розділі Налаштування, Інтеграції, Linear, Невдалі події; кожну можна відтворити одним кліком. DLQ також доступна через функцію webhooks для програмного відтворення.
Пороги кліків і користувацькі тригери
Той самий адаптер Linear обробляє події click_threshold_hook. Пороги задаються на рівні посилання або кампанії в дашборді Elido; issue в Linear створюється при перетині смуги. Сьогодні підтримуються два типи смуг:
- Spike: кліки за останню годину перевищують N-кратне значення ковзного 7-денного погодинного baseline (за замовчуванням N дорівнює 3). Корисно для виявлення вірусного поширення або, що менш приємно, ботового трафіку.
- Cliff: кліки за останню годину падають нижче 10% ковзного baseline. Корисно для виявлення мертвих кампаній - якщо платна реклама була призупинена на стороні джерела, ви побачите тікет у Linear ще до маркетингового стендапу.
Payload click_threshold_hook:
{
"event": "link.click_threshold",
"link_id": "01J9V7QXMZ8K2Y3N4P5R6T7W8Z",
"short_url": "https://s.elido.me/spring-launch",
"band": "spike",
"current_hour_clicks": 8421,
"baseline_hourly_clicks": 612,
"multiplier": 13.76,
"top_referrers": [
{ "host": "news.ycombinator.com", "clicks": 6203 },
{ "host": "direct", "clicks": 1488 }
],
"tags": ["campaign-spring-2026"],
"triggered_at": "2026-06-04T11:14:00Z"
}
Для spike блок рішення каже: "Переконайтеся, що це органічний трафік, а не кампанія з підміни рефереру. Перевірте розбивку рефереру вище." Для cliff: "Переконайтеся, що кампанія ще активна на стороні джерела. Якщо вона була призупинена - заархівуйте це посилання."
Тегова маршрутизація між кількома командами
Стандартного селектора команди достатньо для робочого простору з 20 осіб. У великих організаціях потрібно, щоб тікет Linear за маркетинговим посиланням ішов у команду Marketing, а тікет за посиланням із документації - в команду Documentation. З цим справляється тегова маршрутизація.
Правила маршрутизації зберігаються в integration_configs.routing_json і застосовуються зверху вниз. Правило виглядає так:
[
{
"tag_glob": "campaign-*",
"team_id": "TEAM_growth",
"labels": ["growth", "urgent"]
},
{ "tag_glob": "docs-*", "team_id": "TEAM_docs", "labels": ["docs"] },
{
"tag_glob": "internal-*",
"team_id": "TEAM_internal",
"labels": ["internal"]
},
{ "default": true, "team_id": "TEAM_a1b2c3" }
]
Перемагає перше правило, чий glob збігається хоча б з одним тегом посилання. Якщо збігів немає - спрацьовує правило за замовчуванням. Синтаксис glob збігається з фільтрами збережених представлень Linear, які PM-и вже знають.
Можна також маршрутизувати за failure_type. Деякі команди хочуть, щоб усі TLS-збої йшли до команди платформи - вони зазвичай вказують на помилки конфігурації сертифіката в користувацькому домені тенанта. Додайте правило з ключем failure_type: tls_expired - і готово.
Користувацькі тригери через webhooks
Не кожна команда хоче створювати тікети в Linear для кожного типу подій, що ми публікуємо. Повний каталог подій задокументовано на сторінці функції webhooks, але поширені комбінації, які команди налаштовують поряд із Linear, такі:
link.created- у Linear для аудиту нових посилань (рідко, як правило для compliance-команд)domain.takeover_detected- для TLS-сюрпризів у користувацьких доменахlink.scan_complete- для щотижневих зведених тікетів (один issue на запуск сканування з усіма позначеними посиланнями)
Якщо потрібної події немає в каталозі, її можна побудувати самостійно за допомогою універсального webhook-призначення та нашого посібника з observability. Або просто залиште запит функціональності на нашій публічній Linear-дошці - мета, але рекурсивно.
Тарифи і що доступно на кожному плані
Інтеграція Linear входить у тариф Pro і вище. На Free можна підключити Linear, але доступний лише broken_link_hook (без порогів кліків і користувацьких тригерів). Повну таблицю дивіться на сторінці тарифів. Якщо ви велика команда, що розглядає інтеграцію з міркувань compliance - наприклад, стаття 32 GDPR вимагає виявлення витоків даних через зламані редиректи на домени сквотерів - на сторінці Enterprise-рішень описано, що ми пропонуємо у масштабі.
Матеріали за темою
- Webhooks для подій посилань: посібник розробника - базова шина подій, на якій працюють усі інтеграції, включно з Linear.
- Підключення Sentry до 12 Go-сервісів - як ми моніторимо dispatcher, що запускає події Linear, щоб знати про проблеми самого dispatcher.
- Стратегія запобігання деградації посилань - операційна передісторія, що пояснює, навіщо взагалі будувати виявлення зламаних посилань.
У повному каталозі інтеграцій станом на червень 2026 року 43 вендори, з яких Linear входить до числа 20 активних. Якщо ваша команда використовує Jira - адаптер для нього знаходиться в беті; напишіть нам, і ми його увімкнемо.
Поширені запитання
Як Elido автентифікується в Linear?
Ми використовуємо Personal API Key з областю дії на рівні робочого простору, а не OAuth. Ключ генерується в Linear у розділі Налаштування - API, після чого вставляється в картку інтеграції Elido. Ключ ніколи не виходить з нашого vault і приховується з логів. При ротації ключа наступна подія ініціює м'який запит повторної автентифікації замість тихої помилки.
Що саме вважається зламаним посиланням у події broken_link_hook?
Наш url-scanner щотижня обходить кожне активне коротке посилання і фіксує чотири умови: HTTP 4xx або 5xx при двох послідовних перевірках, прострочений або невалідний TLS-сертифікат, DNS NXDOMAIN та збіг із відомими відбитками припаркованих доменів. Будь-яка з цих чотирьох умов створює один тікет у Linear, дедуплікований за хостом призначення на 24 години - щоб один впалий домен не генерував 800 тікетів.
Чи можна надсилати issue в різні команди Linear залежно від тегів посилання?
Так. На екрані підключення обирається команда за замовчуванням, після чого додаються правила маршрутизації - наприклад, теги виду campaign-* ідуть у команду Growth, а теги виду docs-* - в Engineering. Правила застосовуються зверху вниз із дефолтним fallback. Набір правил зберігається в Postgres, тому зміни доступні в журналі аудиту адміністратора.
Чи працює це і для алертів за порогом кліків, а не лише для зламаних посилань?
Так, починаючи з Phase 12. Той самий адаптер Linear обробляє події click_threshold_hook поряд із broken_link_hook. Пороги задаються на рівні посилання або кампанії в дашборді Elido, і при перетині смуги створюється issue в Linear - або spike (3x базове значення за годину), або cliff (падіння нижче 10% базового значення).
Що станеться, якщо Linear застосує rate limit до інтеграції?
GraphQL-ендпоінт Linear повертає 429 із заголовком Retry-After. Наш webhook-dispatcher враховує це з експоненційним backoff до п'яти спроб, після чого поміщає подію в чергу недоставлених повідомлень. Записи DLQ видно в Налаштування - Інтеграції - Linear - Невдалі події; кожну можна відтворити одним кліком. DLQ також доступна через GraphQL API за адресою /v1/integrations/linear/dlq. Стійкого 429 від Linear у продакшні ми поки не бачили.
Спробуйте Elido
Вставте URL - отримайте коротке посилання
Без реєстрації. Посилання живе 30 днів. Зареєструйтесь, щоб зберегти назавжди.
Безкоштовно, без реєстрації · 2 на день