
Во всём продукте не было ни одного события «пришёл новый отчёт». Уведомления доходили до почтового ящика и больше никуда, так что команде, которой хотелось видеть свои отчёты в n8n, в Zapier или в собственном скрипте, некуда было их направить.
Теперь есть назначение: ваш URL, нужные вам события и ключ подписи. Четыре события, названные один
раз и выводимые дословно везде - report.created, report.status_changed,
report.severity_changed и report.first_viewed. Они становятся интерфейсом с той минуты, как
выходят, потому что кто-нибудь вставит одно из них в свой процесс, а переименование сломает его
молча, поэтому полезная нагрузка несёт собственную версию с первого выпуска.
Что стоит знать, прежде чем что-то на это направлять:
- Каждый POST подписан. HMAC-SHA256 по метке времени и сырому телу, причём метка времени входит в подписываемый материал, так что перехваченный запрос не получится позже воспроизвести против вас.
- Назначение принадлежит команде, а не человеку. Адрес должен продолжать работать, когда тот, кто его добавил, уходит.
- Неудачи повторяются, а потом прекращаются. Задержка растёт примерно восемь с половиной часов, прежде чем попытки прекращаются.
-
Каждая попытка записана. На вопрос «сработал ли вебхук?» отвечает
/app/webhooks, а не чьи-то боевые логи.
URL, который дал клиент, по своему устройству является поверхностью для подделки запросов, поэтому адрес заново разрешается и заново проверяется прямо перед каждым соединением, а не только в момент сохранения, ни одно перенаправление никогда не выполняется, а тело ответа читается ровно настолько, насколько нужно, чтобы закрыть поток.
Страница, которую открывает незнакомый человек
Общедоступная страница отчёта - это в равной мере и демонстрация продукта, и инструмент разбора для владельца, и обеим сторонам нужно от одного экрана разное.
Порядок вкладок был выбран для владельца: то, что написал сообщивший, идёт первым, потому что это самое ценное в отчёте и самое короткое. Это верно для того, кто разбирает собственный ящик, и неверно для того, кому отправили ссылку: он приходил и находил семь слов, с которыми ничего не сделать, а ошибки консоли, неудавшиеся запросы и запись лежали в одном клике и неоткрытыми. Тот, кто не владеет отчётом, теперь попадает сразу на свидетельства, а полоса над вкладками сообщает, что есть в захвате, вместо того чтобы оставлять это на самостоятельное открытие.
У самого плеера было два изъяна, оба видны на одном скриншоте. Его тёмная поверхность растягивалась на всю ширину страницы, так что любая запись уже этой полосы - на широком экране почти любая - оказывалась брошенной посреди чёрного поля. И открывался он на паузе на кадре в нуле, то есть на том, что было на экране сообщившего, пока он ещё тянулся к кнопке записи. Тёмная поверхность теперь стала внутренним отступом самого элемента с видео, так что она облегает запись при любом соотношении сторон, а плеер открывается на кадре, выбранном так, чтобы на него стоило смотреть.
Сообщившему говорят, что станет с его записью
Журнал взаимодействий отказывается сохранять то, что кто-то ввёл в поле пароля. Сетевой журнал по умолчанию скрывает значения учётных данных. Видео показывает экран, на котором их вводили, и с этим ничего не делается.
Один и тот же вопрос, два разных ответа - и лучше всех решить его может сам сообщивший, потому что только он знает, важна ли карточка клиента, открытая за ошибкой. Поэтому теперь ему говорят, чем станет запись, до того как он её начнёт, а не после.
За тремя более мелкими изменениями на другой стороне стоит то же самое чутьё. То, что человек читает собственный отчёт, никогда не шло в счётчик просмотров, но нигде об этом не говорилось; страница отчёта, список отчётов и сводка теперь каждая объясняют, почему число их не учитывает.
Session Replay
Бесплатное расширение для Chrome. Один клик на странице, которая ведёт себя не так, захватывает скриншот, консоль и сетевой журнал и отдаёт вам ссылку, которую можно вставить в задачу.
Захват подешевел, а его скрытие стало единообразным
Захват идёт с плотностью пикселей экрана, если не сказано иначе, так что 6K-экран записывался шириной 6016 пикселей. За эти пиксели платили трижды: при загрузке сообщившим, где они съедают байтовый лимит тарифа, а значит и длительность, которую ему разрешено записать; при хранении, потому что оригинал сохраняется независимо от того, что кодируется рядом с ним; и при каждом перекодировании, где декодирование - дорогая половина. По замерам на боевом сервере тридцатидвухсекундный ролик стоил девять минут пятьдесят четыре секунды процессорного времени. Теперь захват ограничен шириной 1920.
Исправление скрытия важнее. Домен, которому разрешён захват без скрытия, опускал маску заголовков и
строки запроса до одних только названий карт, так что одна и та же запись могла скрыть поле формы с
именем api_key и при этом оставить открытым текстом заголовок X-Api-Key, CSRF-токен и
?password= из того же запроса. Никто так не решал: это были два пути через один файл, отвечавшие
на один вопрос по-разному. Учётные данные в заголовках и в URL маскируются и на домене с
разрешением, а поле паспорта, которое проглатывал список учётных данных, теперь распознаётся как
надо.
Три вещи, которые мы обещали сделать
Их стоит перечислить вместе, потому что о каждой здесь написали раньше, чем её сделали.
Расширение больше не открывает свои иконки и звуки любому источнику. web_accessible_resources
выдавал обе папки всем URL, и ни одна страница никогда ничего оттуда не загружала - расширение
читает собственные упакованные файлы без всякого разрешения. Это был близнец неиспользуемого
разрешения, о котором мы писали в воскресенье, и обоих больше нет; расширение 1.6.2 лежит в
магазине.
Библиотека интеграции отдаётся с наших собственных страниц как 0.4.0, так что identify(),
принимающий любой ключ, который может нести мета-тег, теперь верен не только для тех, кто ставит её
из npm. Три места, где владельцам сайтов всё ещё говорилось, что он принимает пять ключей,
исправлены.
А в половине первого этой ночью MCP-сервер начал сообщать при рукопожатии, что текст, который он передаёт, написан третьей стороной: что комментарий, заголовок, URL и имя в отчёте написал тот, кто сообщил об ошибке, обычно посторонний человек, и что их следует читать и цитировать как данные, а не исполнять как указания. Мы завели это вчера, опираясь на исследование GhostSplice, и написали, почему.
Мелочи
- Отменять и возобновлять подписку решает её владелец.
- Заявленный домен называется доменом везде, где интерфейс его называет, а не сайтом в половине мест.
- Картинки в здешних статьях могут нести подпись, альтернативный текст и размер и вписываются в ту ширину, которую даёт им статья.
- Страницы условий и безопасности переведены на шесть остальных языков, и каждая статическая страница теперь объявляет тот язык, на котором она на самом деле написана.
- API выдаёт одну сессию на токен, а не одну на обновление, и страница токенов читается как одна строка на токен.