Commit Graph

4316 Commits

Author SHA1 Message Date
Дмитрий de0b09331c Билайн: опрос судьбы перестал глотать отказ молча
Accessibility (Pa11y live) / a11y (push) Has been cancelled
SAST — Semgrep / Semgrep SAST scan (push) Has been cancelled
Беда. Платформа Билайна отдаёт отказ кодом ответа 200, а слова кладёт в тело:
{"error":{"code":"-20107","message":"Ошибка авторизации"}}. Отправка это уже
проверяла, а опрос судьбы — нет: fetchOne звал разбор напрямую, разбор поля
`error` не смотрит и возвращал пустой список, неотличимый от честного «такого
сообщения нет».

Чем грозило. Сломается ключ — судьба сообщений просто перестанет обновляться,
МОЛЧА. А за «не доставлено» клиенту возвращаются рубли (В-198), то есть
молчание = невозвращённые деньги. Тот же класс, что 04.08 с уровнем журнала.

Правка. В fetchOne перед разбором прогоняется уже готовый kodOshibki(); нашёлся
код — бросается SmsSendException с terminal: false. Не окончательный намеренно:
судьбу всегда можно переспросить следующим заходом, в отличие от отправки.
Приёмник обратного звонка платформы не тронут — у него своя дорога.

Кто ловит. PollClientSmsDeliveryCommand уже пишет Log::warning и идёт дальше;
у Билайна пачка = 1 сообщение, так что отказ стоит одного номера за заход, а не
всего прохода. Warning на бою слышен — ниже него журнал глотает (урок 04.08).

Доказано, а не «должно работать». Тест написан ПЕРВЫМ и был увиден красным:
без проверки падал ровно один тест, новый, со словами «опрос прошёл молча»,
остальные 15 стояли зелёными. Вторым тестом закрыта обратная сторона: ответ без
отказа и без действий по-прежнему считается честным «сообщения нет» и НЕ роняет
заход — иначе один забытый номер срывал бы весь опрос.

Прогон: СМС 577/577, 7155 проверок (было 575/575 и 7151 — ровно на два теста и
четыре проверки больше). Pint чист, PHPStan 0 ошибок.

На бой НЕ выкачено — отдельным разрешением владельца.
2026-08-11 05:24:34 +03:00
Дмитрий df70a78e17 merge: ветка Билайна и Мотива сведена с главной — 347 коммитов, один затык
Затык был ровно один — routes/web.php: главная добавила ручку суточного итога
сторожей с машины робота, ветка добавила приёмник статусов Билайна. Ручки
независимые, оставлены обе.

Попутно поправлено примечание в config/services.php: оно говорило «заявка подана,
срок до десяти рабочих дней», а имя `Liderra.ru` было ОДОБРЕНО обеими сетями
10.08.2026 в тот же день — проверено глазами в кабинете. Примечание, которое
врёт, хуже отсутствующего: следующая смена прочла бы его и не стала поднимать
выключатель.

Замер на сведённом коде:
- модуль СМС 575/575, 7151 проверка (опора ветки была 548 — главная принесла 27);
- фронтенд 2205 из 2210. Пять падений — ЧУЖИЕ и приехали из главной:
  KoshelyokZakladkiPoKanalam.spec.ts, экран AdWalletMoneyColumn.vue спотыкается
  об отсутствующее поле frozen_breakdown. Доказано отпечатками: и тест, и экран
  байт в байт совпадают с gitea/main, моя правка их не касалась;
- Pint и PHPStan — чисто.
2026-08-10 21:39:33 +03:00
Дмитрий a159bf73cb feat,смс: портал научился сети Мотива — маршрут через Билайна на выключателе
Номер абонента Мотива не доходил даже до каналов: словарь операторов о Мотиве
не знал, и номер выбывал на первой заставе «кому мы вообще шлём».

Что сделано:
· словарь знает ОБА сырых написания — торговое «Мотив» от ДаДаты и юридическое
  ООО "ЕКАТЕРИНБУРГ-2000" из реестра Россвязи, где слова «Мотив» нет ни разу
  замер по DEF-9xx.csv: 29 диапазонов, среди 89 имён реестра столкновений нет;
· Мотив добавлен к четвёрке владельца — сетей стало пять;
· маршрут через Билайна стоит на выключателе SMS_BEELINE_SERVES_MOTIV,
  умолчание ВЫКЛЮЧЕНО: до одобрения имени отправка вернёт 20230, а этот отказ
  окончательный — повтора нет, сообщение умрёт;
· цена по сети, а не одна на канал: 770 копеек за Мотива. Экран сверки тоже
  научен считать по сети — иначе занижал бы расход на 1,84 ₽ с сообщения;
· проверка ввода настроек и галки в админке пропускают Мотива: без этого
  владелец не смог бы его отметить, а заполненный список отменяет код;
· на клиентском экране «Имя отправителя» появилась пятая строка — скрыть её
  значило бы солгать умолчанием.

Тесты: модуль 548/548, было 530; 1801 проверка. Фронтенд 120/120, Sales 483/483.
Контрольные прогоны: убранное юридическое написание красит ровно четыре
зависящих от него теста, перевёрнутое умолчание выключателя — ровно один.

Не выкачено. Включать после того, как Билайн согласует имя — ориентир 24.08.2026.
2026-08-10 20:27:55 +03:00
Дмитрий 9bdced8173 docs: два промта следующим сменам — сведение ветки в главную и робот МТС
Accessibility (Pa11y live) / a11y (push) Has been cancelled
**Сведение ветки в главную** (`2026-08-10-PROMT-svedenie-vetki-smeny-v-glavnuyu.md`).
Замерено: 262 коммита рабочей ветки против 14 коммитов главной, 735 файлов.
Конфликтов всего три, и все решаются «берём версию ветки» — доказано замером:
по обоим спорным файлам их версия оказалась строгой надстройкой (ноль удалённых
строк). Главное предупреждение не про сведение, а про то, что после: боевой не
равен ни одной ветке, а `routes/web.php` на бою существует в виде, какого нет
нигде в git. Выкат целиком после сведения сотрёт работающее.

**Робот МТС** (`2026-08-07-PROMT-mts-bot-kabinet-otbivaet-brauzer.md`).
Совет из письма-тревоги («нужен другой адрес выхода») ошибочен — доказано тремя
опытами: кабинет отдаёт 403 именно браузеру робота, а обычный запрос с той же
машины, и напрямую, и через прокси, получает нормальный 401. Отдельно вынесен
живой риск: оплаченная кампания идёт, а портал за ней не видит.

Оба написаны по одному правилу: сначала то, что уводит не туда, потом замеры,
потом отдельным разделом «что НЕ доказано» — чтобы догадки не выдавались за факты.
В каждом — раздел граблей, на которые смена наступила сама.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 19:05:54 +03:00
Дмитрий 6201ed59fd chore(сторож секретов): в главную доехали разрешения на рабочие номера дела
Accessibility (Pa11y live) / a11y (push) Has been cancelled
SAST — Semgrep / Semgrep SAST scan (push) Has been cancelled
Найдено 10.08.2026 при попытке отправить починку разводки лидов: сторож секретов
объявил три находки с пометкой 152-ФЗ и запер отправку. Находки оказались не
новой утечкой, а следствием того, что настройка сторожа в главной отстала.

Что было на самом деле: в этот же день вторая смена внесла в `.gitleaks.toml`
разрешения на рабочие номера дела — по решению владельца. Это номер, С КОТОРОГО
звонит наш обзвон (в человеческой записи и в той, какой его пишет Asterisk), и
пять номеров из прайса оператора. Разрешены ПО ЗНАЧЕНИЮ, а не по файлу: сами
документы остаются под охраной, любой другой настоящий номер в них сторож
поймает по-прежнему.

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

Проверено после переноса: `gitleaks detect` с настройкой проекта — 8335
коммитов, «no leaks found».

NB для следующей смены: я сначала решил, будто трёх файлов настроек (.gitleaks.toml,
.gitleaksignore, .lychee.toml) в главной нет вовсе, и чуть не записал это в
историю. Проверка `git cat-file -e ветка:.файл` давала ложный отрицательный ответ
на именах с ведущей точкой. Верный способ — `git ls-tree --name-only ветка`.
Файлы на месте, отстало только содержимое одного из них.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 18:47:59 +03:00
Дмитрий 700fa5455a fix(лиды): кириллический домен больше не принимается за СМС — лид по .рф доезжает до клиента
Беда, пойманная на бою 10.08.2026: лид 683 по проекту 'B2_автозаим.рф' не
развёлся ни одному клиенту. Работа падала 35 раз с 10:35 до 16:02, потом сдалась
— лид остался недоставленным.

Причина не в поставщике и не в данных, а в разборе строки проекта. Тип сигнала
угадывался по виду строки: телефон — звонок, домен — сайт, всё остальное — СМС.
Но оба правила «это домен» были написаны только под латиницу: `[a-z0-9-]` и
окончание `[a-z]{2,}`. Строка `автозаим.рф` под них не подходила и проваливалась
в последнее правило «значит, СМС». А в справочнике поставщика тот же ключ
записан как 'site' — типы не сошлись, и разводчик отказался работать.

Замерено на бою: таких проектов пять, все на .рф — авто-займ-124.рф,
автозаим.рф, автоломбард-экспресс.рф, займ-24.рф, сфера-займа24.рф. Из них
включён один (автозаим.рф, план 15 лидов в день), остальные четыре — мины на
случай включения.

🔴 Это ТРЕТИЙ случай одной семьи. 18.05.2026 так же не распознался домен внутри
свободного текста ('B1_заявка carmoney.ru/') — тогда застряло 22 живых лида.
Оба раза причина одна: разбор судил по алфавиту, а не по строению строки.
Теперь правило одно и записано в коде объяснением: домен опознаётся по точке и
буквенному окончанию, буквы считаются любые (\p{L} + флаг u).

Граница проведена намеренно: кириллица сама по себе сайтом не считается. Слово
без точки ('АкцияЛето') остаётся СМС-ключом — иначе лечение было бы хуже
болезни. Охраняет отдельный тест.

Проверено: новые тесты сначала упали, причём три из четырёх — дословно с боевой
ошибкой. После правки 44/44 в тестах разводки и 467/467 по поставщику,
вебхукам, деньгам и имитации. Pint чист, статанализ по моим файлам чист.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 18:03:39 +03:00
Дмитрий 272ccbffe0 feat,смс: приёмник статусов Билайна — платформа сама сообщает судьбу
Билайн умеет звонить нам сам: POST на /api/webhook/beeline-delivery/{secret}
с полями ORDID, CNRID, RESCOUNT, STATUS, FINALTIME. Раньше судьбу сообщения
добирал только опрос — теперь она приходит сразу, как у МТС и Теле2.

Защита та же, что у двух соседних приёмников: секрет короче 32 знаков или
пустой = приёмник закрыт наглухо; сверка секрета через hash_equals; список
адресов отправителя необязательный, пустой список объявляется в журнале;
ограничитель 600 обращений в минуту; на чужой адрес и на неверный секрет
отвечаем 404, а не 403, чтобы не подсказывать чужому, что дверь тут есть.

Записи в журнал уровня warning, не notice: на бою LOG_LEVEL=warning и всё,
что ниже, не доезжает вовсе.

12 тестов написаны до кода, каждый посмотрен красным. Защита проверена
подсовыванием ошибки — краснеют ровно те тесты, что должны. Модуль целиком
530/530, pint чисто, статанализ 0.

Адрес приёмника в кабинете Билайна ещё не заявлен и секрет на бою не задан.
Пока их нет, приёмник закрыт, а канал работает по-старому через опрос.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 16:38:11 +03:00
Дмитрий 977c10bdba feat,смс: канал Билайна — отправка, судьба сообщения и вход двух видов 2026-08-10 12:08:51 +03:00
Дмитрий fb40aaf7c0 fix,смс: канал МТС переиспользует соединение и замолкает при обрывах
Защита оператора считает не запросы, а попытки ОТКРЫТЬ соединение. Прежний код
собирал HTTP-клиент заново на каждое сообщение: рассылка на тысячу номеров
открывала тысячу соединений подряд и выглядела для их защиты как атака, после
чего адрес уходил в чёрный список на часы. Замеры 05-07.08.2026, заявка
RUMAAS-73856: из шести одинаковых запросов проходили один-два, остальные
молча дропались, пауза пять минут доступ не возвращала.

Что сделано:

- общий обработчик curl на объект — шесть запросов идут по ОДНОМУ соединению
  вместо шести. Замерено вживую на безобидном узле: начиная со второго запроса
  установка соединения и согласование шифрования равны нулю, время запроса
  втрое меньше — 0,13 с против 0,41 с;

- предохранитель SmsConnectionBreaker: пять обрывов подряд — и канал молчит
  десять минут, в сеть не выходя вовсе. Это лечит главное: раньше каждая
  неудачная попытка сыпала семь безответных стуков и сама продлевала
  блокировку. Считаются ТОЛЬКО обрывы связи; прикладной отказ вроде
  отсутствия имени отправителя предохранитель не трогает — сеть-то жива;

- ожидание соединения 3 с вместо прежних десяти, чтобы не копить оборванные
  попытки, и своё имя клиента LiderraSms/1.0 вместо безымянного робота.

Подменяется обработчик, а НЕ клиент целиком: подмена клиента отключила бы
подделку сети в тестах, и они пошли бы в настоящий интернет. Записано
комментарием в коде.

Поведение отправки не меняется. Мост SMS_MTS_CONNECT_TO не тронут, заявка
RUMAAS-73856 остаётся открытой.

Проверено: 500 тестов канала зелёные, статанализ ноль замечаний, оформление
чистое. Новый сторож перед починкой был красным.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 16:00:17 +03:00
Дмитрий 3699ece6e3 защита: в главную ветку доставлены пять починок сторожа боевой базы — новые рабочие папки больше не рождаются дырявыми
По прямому слову владельца 07.08.2026 («выкати в мэйн, только всё проверь, чтоб никого не потёр»).

🔴 ЗАЧЕМ. Замерено смено́й 33: тело сторожа `172931cf` лежало в 13 рабочих папках из 23,
включая ЭТУ ветку. В нём не было НИ ОДНОЙ починки от 05.08 и 07.08. Хук подключён в настройках
ОТНОСИТЕЛЬНЫМ путём, значит исполняется тело, лежащее рядом с папкой сессии, — и всякая
НОВАЯ рабочая папка, отведённая от главной ветки, рождалась с дырявым сторожем.

🔴 ЧТО ПРОПУСКАЛО СТАРОЕ ТЕЛО (замерено живым вызовом, одним прибором по обоим файлам):
  · php artisan db:wipe --force --database=liderra
  · php artisan migrate:fresh --force
  · dropdb "$PROD_DB"                       (цель спрятана в переменной)
  · psql "$PROD_URL" -c "DROP SCHEMA public CASCADE"
Четыре красных из семи образцов. Контрольный образец (снос кластера) старое тело
останавливало — значит замер работал и не красил всё подряд.

🟢 ЧТО СТАЛО. Тот же замер по этому файлу после доставки: 0 красных из 7. Обе мирные
команды (обычная миграция `php artisan migrate`, снос тестовой базы `dropdb liderra_testing`)
по-прежнему проходят.

ЧТО ИМЕННО ДОБАВЛЕНО В СТОРОЖА:
  4. штатная программа dropdb (стоит на этой машине)
  5. SQL DROP SCHEMA … CASCADE — базу оставляет, содержимое выносит
  6. снос средствами приложения: db:wipe / migrate:fresh / migrate:refresh
  + короткие имена облака (yc mdb pg / yc mdb postgresql)
  + цель, спрятанная в переменной, обязана быть названа словами
🔴 Цена строгости, названная честно: снос ТЕСТОВОЙ базы по связи из переменной теперь тоже
останавливается — сторож не может знать, что под переменной тестовая. Обе двери владельца
(маркер PROD-DESTROY-OK и ALLOW_PROD_DB_DESTROY=1) работают.

Указатель `prod-db-pointer.mjs` доставлен тем же коммитом: он рассказывает сессии, что ловит
сторож, и в старом виде ВРАЛ — называл 5 приёмов из 6 и прямо обещал, что снос со спрятанной
целью пройдёт.

🔴 ЧТО ПРОВЕРЕНО, ЧТОБЫ НИКОГО НЕ ЗАТЕРЕТЬ:
 1. различия обоих файлов просмотрены построчно: из прежних тел не пропало НИ ОДНОЙ мысли —
    все прежние строки либо сохранены, либо заменены своими же расширенными видами;
 2. в этой папке идёт ЧУЖАЯ незакоммиченная работа по СМС (правка MtsSmsProvider.php,
    новые SmsConnectionBreaker.php и MtsSmsProviderConnectionTest.php, ПРОМТ-следующей-смене.md).
    Она НЕ тронута и в этот коммит НЕ входит: добавлены строго два файла поимённо;
 3. 🔴 на сервер GitHub НИЧЕГО не отправлено. Замерено: тамошний main разошёлся с местным
    очень сильно — местный впереди на 3572 коммита, серверный впереди на 1525, последний
    серверный коммит от 03.06.2026. Любая отправка туда либо будет отвергнута, либо снесёт
    полторы тысячи чужих коммитов. Это отдельное решение владельца, а не часть этой работы.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 15:54:24 +03:00
Дмитрий 1c08944bf1 docs: вернулись ещё два документа, поправлена ссылка на исчезнувшую рабочую папку — проверка ссылок стала зелёной
Accessibility (Pa11y live) / a11y (push) Has been cancelled
SAST — Semgrep / Semgrep SAST scan (push) Has been cancelled
Продолжение предыдущего коммита. Возвращённые документы сами ссылались на два
файла, которых в git тоже не было: HANDOFF по состоянию клиентской рассылки и
её design-spec от 25.07. Оба лежали только на диске — вернул.

Осталась одна ссылка, которую возвратом не починить: приёмка от 27.07 указывала
на файл внутри временной рабочей папки `.claude/worktrees/client-sms`, а такой
папки давно нет. Переписал на настоящий путь в репозитории — файл на месте,
строка та же.

Итог: `lychee` командой самого хука даёт 0 ошибок (было 20). Отправка на сервер
снова открыта — она была закрыта для ВСЕХ смен, а не только для этой.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 15:00:50 +03:00
Дмитрий 930e28d2bf docs: возвращены в git 16 документов, на которые главная ссылалась, а их там не было
Найдено 07.08.2026 при попытке отправить починку сторожа пульса: проверка ссылок
падала на 20 битых ссылках, и ни одна не была моей. Оказалось, что закоммиченные
документы ссылаются на файлы, которые лежали только на диске рабочей машины и в
git не попали ни разу. То есть главная не проходила проверку сама по себе — и
отправка была закрыта ДЛЯ ВСЕХ смен, а не только для меня. У соседней смены на
этот момент висело 5 неотправленных коммитов.

Что вернулось: разборы и промты смен по клиентской СМС-рассылке (этапы 1-5,
задачи 5-9, конец июля) и три промта смен 25-26 по кошельку и телеграму от
06.08. Все 16 — ровно те, на которые ссылались уже сохранённые документы, то
есть их отсутствие было пропажей, а не задумкой.

Отбор не на глаз: список получен из вывода lychee, каждый файл проверен на
диске и на отсутствие в git.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 14:54:26 +03:00
Дмитрий 29daf584ea fix(сторож пульса): свежая команда в расписании не считается умершей, ожившая закрывает свою жалобу
Живой случай 07.08.2026. Выкат в 12:04 добавил три ежедневные команды
(obzvon:chistka 03:45, obzvon:chistka-materialov 03:50, lena:proverka-obhoda
06:10). Их время в этот день уже прошло, записи пульса не было — и часовой
сторож с окном дедупа 60 мин заводил три жалобы КАЖДЫЙ ЧАС, каждая со своим
письмом владельцу. К утру набежало бы под полсотни. Тем же способом 05-06.08
набралось 18 записей про incidents:watch-failures.

Две правки:

1. Нет записи пульса — не жалуемся, а заводим отметку «команда известна с
   этого мгновения» и молчим, пока не выйдет срок первого запуска: два
   ожидаемых интервала, отсчёт от отметки. Не отработала за срок — жалоба будет.

2. Команда снова здорова — её открытые жалобы гасятся. Без этого записи копятся
   навсегда: 06.08 сторож починился в 20:37, а 18 жалоб остались открытыми, и
   лампа «Здоровье портала» горела сутки после устранения причины. Кнопки
   «закрыть инцидент» в админке нет.

Якорь пробел-тире в поиске жалобы обязателен: без него имя команды совпало бы с
любой другой, начинающейся так же. Обратный слэш в именах джобов экранируется —
в LIKE Postgres он служебный.

Тесты: 5 новых, из них 3 сначала красные, каждый по своей причине; 2 сторожевых
держат границы — молчание не вечно, больную команду не закрываем. Прогон 13/13,
соседние 84/84, composer stan 0 ошибок, pint чисто.

Выкачено на боевой 07.08.2026 14:30 МСК: тревог стало 0 вместо 3 в час.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 14:36:22 +03:00
Дмитрий b65ad2ecf8 merge: рабочая ветка сведена в главную — вкладка «Активность» отвечает «жив ли клиент», плюс обзвон, телеграм и запрет переадресации
Accessibility (Pa11y live) / a11y (push) Has been cancelled
SAST — Semgrep / Semgrep SAST scan (push) Has been cancelled
# Conflicts:
#	docs/observer/STATUS.md
#	docs/superpowers/runbooks/2026-08-06-rezultaty-priyomki-telegram.md
2026-08-07 11:31:42 +03:00
Дмитрий 8d96cda70b docs: в отчёт смены вписаны номера обоих коммитов
Чтобы файл читался сам по себе, без обращения к истории.
2026-08-07 10:39:39 +03:00
Дмитрий 171f531b61 docs приёмка: Т-М2 закрыта — живое одобрение МТС с движением денег
07.08 в 10:31 МТС одобрил кампанию №15. Числа сошлись с посчитанными ЗАРАНЕЕ
до копейки: кабинет взял 182.40, наценка 1.4 → списано 255.36, остаток 13.44
отпущен в ту же секунду, баланс 9869.50 → 9614.14, заморожено → 268.80.

Одобрение чуть не потерялось: кабинет написал седьмое слово «Запущена», словарь
робота знал шесть. Снаружи это неотличимо от «вердикта нет» — вскрыли, заглянув
в кабинет разовой пробой на чтение. Чинились ОБЕ половины (разбор и поиск ряда),
как предупреждает комментарий в коде; сторожа на обеих, тесты робота 202 → 206.

Непроверенной во всём блоке осталась одна вещь — живая половина пересдачи Т-М4:
для неё нужен свежий отказ МТС, а кампания одобрена.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 10:39:25 +03:00
Дмитрий 9ba2a6a49b fix(безопасность): за переадресацией не ходим — тайный ключ больше не уезжает чужому
Дверь проверяет адрес из настройки. Если разрешённая машина отвечает «иди на
другой адрес», перевозчик по умолчанию туда идёт и везёт наш заголовок дальше:
при уходе на чужой адрес Guzzle снимает только Authorization и Cookie, а
X-Render-Key и X-Obzvon-Key не из них.

Замерено до правки на подставных машинах: ключ рендера доехал до неразрешённой
машины из ленты Яндекса, из поиска клиентов одиночным запросом и пачкой, из
плитки прокси — и плитка при этом горела зелёным, показывая ЧУЖОЙ IP как свой.
Ключ голосового робота уезжал вместе с заданием.

Поставлен withoutRedirecting в пяти строениях запроса четырёх файлов. У
SelfRenderClient их два: пачка строит запрос сама, и запрет из одиночного пути
туда не доезжает — проверено вырезанием, снятие запрета только с пачки роняет
отдельного сторожа и даёт по утечке на каждый адрес порции.

Новых настроек не заводил: тумблер «сюда переадресовывать можно» и был бы той
дырой, ради которой запрет ставится.

Сторожа: app/tests/Feature/Security/KlyuchNeEdetPoPereadresaciiTest.php, 8
проверок, смотрят на запись переговоров, а не на текст исходника. Каждый показан
красным снятием своего запрета по одному. Отдельная проверка «датчик сам жив»
падает, если подставная сеть перестанет ходить за переадресацией, — иначе
остальные сторожа молча стали бы пустыми.

Отчёт смены: docs/superpowers/priyomka/stroyka-7/otchyot-pomoshchnika-zapret-pereadresacii-2026-08-07.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 10:37:22 +03:00
Дмитрий 9f165a49cb chore: замечания линтера в новых тестах — auto-import Vuetify и явный неразрывный пробел 2026-08-07 09:54:30 +03:00
Дмитрий cc9a1a91a7 docs: заведён отчёт смены по запрету переадресации с тайным ключом
Скелет разделов. Пишется по ходу работы, чтобы не сгорело при обрыве.
2026-08-07 09:38:26 +03:00
Дмитрий d45c495654 feat: точка состояния клиента в списке — видно пропавших без открытия карточки 2026-08-07 09:30:35 +03:00
Дмитрий 459947f76b Р126 третья дверь: работа оборванного круга сохранена и принята, дыра переадресации найдена
Круг смены 6 оборвали средой, работа помощника лежала в дереве несохранённой и её снёс бы
первый же чужой откат. Замерил целостность, прочёл его отчёт, прогнал своей рукой, вынес
приговор. Заново ничего не переделывал.

ПРИНЯТО. Третья и последняя дверь с ключом рендера закрыта той же проверенной дверью.
Список разрешённых машин общий с рендером и это доказано работой, а не доводом. Закрытая
дверь красит СЕРЫМ, а не красным, и ключ при этом физически никуда не уходит, замерено мной
двумя случаями по отдельному запуску на каждый.

Помощник сверх задания нашёл и починил ложь, которой никто не искал: подпись плитки называла
серый словами не отвечает, то есть гнала владельца продлевать исправные прокси.

Мои ошибки называю первыми, их три.

Пятьдесят девятая. Я назвал adminDashboardHelpers.ts чужим файлом соседней смены прямо в
промте смене 7, в списке не трогать и в коммит не брать. Взял из головы, не замерив. Вся
правка в этом файле - работа моего же помощника. Исполни следующая смена мой промт дословно,
починка подписи плитки не попала бы в коммит и сгорела.

Шестидесятая. Мой снимок оборванного круга был неполон: записал шесть файлов, их семь.
Перечень собрал командой, но раньше, чем помощник закончил, и не перемерил перед тем, как
назвать его окончательным.

Шестьдесят первая. Мой датчик прогона искал не то слово и я чуть не объявил состоявшийся
прогон несостоявшимся. Спас узкий прогон, которым я прибор перепроверил.

Вырезание второго рода дало дыру. Допущение защиты: дверь проверяет адрес из настройки и
считает, что запрос уйдёт именно туда. Случай мимо: разрешённая машина отвечает иди на другой
адрес. Замерено на двух подставных машинах: тайный ключ уехал на машину, которой в списке
разрешённых НЕТ, а плитка осталась ЗЕЛЁНОЙ и показала чужой адрес как свой. Перемерил на
живой двери боевого Поиска клиентов тем же ножом, отдельным запуском - то же самое. Причина
прочитана в исходнике библиотеки: при уходе на чужой адрес снимаются только два заголовка,
и нашего среди них нет. Вторым прибором замерено, что отключения переадресации нет нигде во
всём боевом коде. Это не отменяет Р126, дверь делает обещанное на своих случаях, но обещание
шире дела и про это не сказано нигде. Отдельным кругом.

Датчики: полный прогон моей рукой на своей базе 5344 проверки, 5340 зелёных, 4 пропущено,
красных 0, арифметика сходится. Проверки интерфейса 3 из 3. Разметка 0 ошибок.
2026-08-07 09:29:23 +03:00
Дмитрий 5559be88f5 feat: вкладка «Активность» переведена на новую панель, колонка пользователей — на живой последний вход 2026-08-07 09:25:33 +03:00
Дмитрий 2008e9f082 feat: панель «Активность» — вердикт, полоска 90 дней, лента дел 2026-08-07 09:03:16 +03:00
Дмитрий b560efd1f9 feat: русские фразы ленты, расшифровка устройства и подписи вердикта 2026-08-07 08:59:32 +03:00
Дмитрий 654781102f feat: типы и маппер под блок «жив ли клиент» и ленту дел 2026-08-07 08:54:44 +03:00
Дмитрий 250ecf03c4 style: pint — импорт User в тесте списка клиентов 2026-08-07 08:45:33 +03:00
Дмитрий 7c646d3c7c fix: список клиентов сортируется по живому журналу входов, а не по мёртвой колонке 2026-08-07 08:43:25 +03:00
Дмитрий 61182a1c55 docs обзвон: конец смены 6, проверка расписания закрыта живьём, круг 7 оборван
Смену остановил владелец. Довожу до логического конца.

Проверка 1 задачи З-0.10 закрыта ЖИВЬЁМ. Доказать её раньше 02:20 ночи было
нечем, я записал замену и назвал вслух, чего она не доказывает. Дождался и
замерил: 07.08.2026 в 02:20:01 машина робота обошла своих сторожей САМА, без
человека, за две секунды, все три зелёные, итог лёг со своей датой. Уборка
записей чужих голосов перестала зависеть от человеческой памяти, и это замерено,
а не обещано. Журнал того же обхода честно говорит отправка не настроена:
портальная половина не выкачена, и краснота одной проверки из 42 у сторожа обхода
и есть датчик завершённости выката.

Круг 7 оборван на середине. Помощник закрывал третью дверь с тем же тайным ключом
и не успел сохранить работу коммитом. Файлы перечислены поимённо в промте смене 7,
раздел 3.2, вместе с порядком: замерить целостность, прочесть его отчёт, прогнать
своей рукой, вынести приговор, НЕ переделывать заново. Приёмочный лист по этому
кругу не заведён, и это записано.

Итог смены. Задач 54, врезок ПОСТРОЕНО 19, требований 112, решений владельца 127.
Полный прогон 5301 проверка, 5297 зелёных, 4 пропущено, красных 0.

Мои ошибки: их одиннадцать, с 48 по 59, и все одного класса, прибор мерил не то,
о чём я спрашивал. Тяжелейшие три. Пятьдесят пятая: построил главный довод
задания на ложном замере, назвав упоминания зовущими. Пятьдесят восьмая: назвал в
задании одну дверь с тайным ключом, а их оказалось три. Пятьдесят девятая: вынес
владельцу цену решения, взятую из головы, а не из замера.

Правил стало 30, шесть добыты этой сменой.
2026-08-07 08:41:29 +03:00
Дмитрий 0bf43bfd1f docs приёмка: Я3 и Я4 закрыты по сроку — последние комбинации Яндекса 2026-08-07 08:38:44 +03:00
Дмитрий 8167dc7d79 docs приёмка: Я3 и Я4 закрыты по сроку — последние комбинации Яндекса
Срок обеих кампаний истёк 07.08 в 00:00 UTC, портал сам закрыл их и вернул
неоткрученное. Числа сняты с боевой базы, арифметика сходится до копейки:
833.50 - 9.00 = 824.50 и 833.50 - 40.50 = 793.00.

Я-Д5 воспроизвёлся трижды за четыре секунды на разных суммах — возврат по сроку
работает не по случайности.

Предсказание сбылось наполовину: Я4 обещали ~160 показов, вышел 81; Я3 обещали
ноль, вышло 18. Скорость по одному часу для суточного предсказания не годится.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 08:37:58 +03:00
Дмитрий d7b77d25f2 docs обзвон: приговор по восьмёрке в номере, цена решения названа честно
Решение владельца Р127 исполнено коммитом 56ddaa1e. Мой нож замерил: восьмёрка и
семёрка дают теперь ОДИН знак и ОДНО тело, границы держатся, семизначный и
тринадцатизначный номера не тронуты, казахстанский со своим знаком, и правило
устойчиво к повторному приведению.

Моя ошибка первой, пятьдесят девятая. Вынося развилку владельцу, я написал, что у
одиннадцати цифр с восьмёркой второго толкования нет. Я взял это из головы, НЕ
ЗАМЕРИВ. Второе толкование есть: иностранные номера длиной ровно одиннадцать
цифр с кодом на восьмёрку. Большинство дают несуществующий российский номер, но
вьетнамский превращается в живой подмосковный код, и род ошибки меняется с
звонок не состоится на звонок состоится, но не тому человеку.

Правило велит выносить развилку с полным набором дорог. Дороги я вынес полные, а
цену неполную, и владелец решал, не зная её.

Смягчает это одно, и не моя заслуга. Помощник докопал дальше и поправил САМ СЕБЯ:
общий нормализатор телефонов портала живёт в двадцати файлах, включая сам обзвон,
и делает ровно то же самое. Вьетнамский номер портится на входе везде уже
сегодня. Р127 опасности не добавляет, он прекращает расхождение обзвона с
остальным порталом.

Его находка, которую я перемерил своим прибором и подтверждаю: пара из десяти и
одиннадцати цифр даёт ДВА знака на одного человека, и ему позвонят дважды. При
этом общий нормализатор и проверка запрета звонить считают ту же пару ОДНИМ
человеком. То есть беда, ради которой принято Р127, на этой паре жива. Он не стал
чинить и правильно: лечение шире решения, надо сводить три разных канона
телефона, живущих в обзвоне, а один из них сторожит запрет звонить. Вынесено
открытым вопросом первым номером.

Ошибка помощника, названная им первой, редкого рода: он назвал цену нечестно и
едва не отдал её в таком виде, подав общую беду портала как новую опасность
решения. Проверил дальше и поправил себя прямым текстом. Это ровно то, чего метод
требует от надзирателя и чего надзиратель на этот раз не сделал: сперва замер,
потом слово.

Датчики: решений 127, разметка 0 ошибок, правописание протокола 0 жалоб.
Прогон 5301 проверка, 5297 зелёных, 4 пропущено, красных 0.
2026-08-07 08:36:21 +03:00
Дмитрий c808188c57 feat: карточка клиента отдаёт «жив ли» и ленту дел вместо журнала сделок 2026-08-07 08:34:30 +03:00
Дмитрий 69ba292d17 feat: сервисы «жив ли клиент» и ленты дел для карточки клиента 2026-08-07 08:27:23 +03:00
Дмитрий 56ddaa1ed4 fix обзвон: один человек, записанный через 8 и через +7, получал два звонка
Решение владельца Р127. В `odinVidNomera` восьмёрка приводится к семёрке
ТОЛЬКО когда цифр ровно одиннадцать. Короткие и длинные номера не трогаются
вовсе: слить двух разных людей в один знак — ошибка тише и хуже, второму не
позвонили бы никогда и молча.

Замерено до правки: `8 999 000-00-01` и `+7 999 000-00-01` давали два разных
знака и два разных тела. Сторожа смотрят на то, что вправду уехало роботу, и
сравнивают дословно — так же, как сравнивает приёмник.

Сторожа показаны красными тремя сломами: без починки, без проверки длины и с
приведением к восьмёрке вместо семёрки. Возврат доказан слепком файла.

Названная владельцу цена: иностранные одиннадцатизначные номера с кодом на
восьмёрку это правило портит. Вьетнамские `8496…`/`8497…`/`8498…` станут
похожи на живые коды Московской области — робот позвонит чужому человеку.
Лечится чисткой номеров на входе, это отдельная задача. Подробности и
незакрытые хвосты — в отчёте.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 08:25:28 +03:00
Дмитрий 09ed5e1b31 docs обзвон: приговор по двери боевого рендера, дверей оказалось три
Решение владельца Р126 исполнено коммитом 92472816, и исполнено ШИРЕ, чем я
заказал.

Моя ошибка первой, пятьдесят восьмая. Я назвал в задании ОДНУ дверь, через
которую уходит тайный ключ боевого Поиска клиентов. Помощник замерил: дверей
ДВЕ, и вторая шлёт тот же ключ по той же настройке. Перепроверил вторым прибором
на версии до его правки: у второй двери был ровно тот же вид проверки и тот же
заголовок с ключом. Почини он только названный мной файл, решение владельца
осталось бы невыполненным, а дыра открытой. Отсюда правило 29: одно найденное
место это находка, а не перечень.

И третья дверь нашлась потом: та же тайна уходит из плитки срока прокси по
другой настройке. Помощник назвал её и НЕ тронул, правильно. Перемерил сам,
вынес владельцу, закрыто отдельным заходом.

Мой нож прогнал одиннадцать форм адреса на боевом окружении с умолчанием списка
машин из хранилища. Пять законных форм открыты, шесть опасных закрыты, и главное
опечатка в адресе машины ловится, а именно она уводила ключ чужому молча и
навсегда. Обратный край тоже верен: при пустом списке дверь закрыта совсем, а
местный адрес без шифрования проходит только не на боевом.

Помощник назвал свою ошибку первой, и она новая для этого проекта: он запустил
полный прогон раньше, чем закончил правку стиля, и через четыре минуты форматтер
переписал два его файла прямо во время прогона. Зелёный цвет такого прогона не
доказывает ничего. Отсюда правило 30.

Вторая его ошибка честнее первой: проверка покраснела на его же оплошности, и
первым побуждением было подогнать код под ошибку. Поправил проверку.

Оговорка, которую называю вслух. Боевое значение настройки адреса НЕ ЗАМЕРЕНО и
замерить его нельзя, это доступ к боевому. Перед выкатом нужна одна команда,
показывающая, начинается ли адрес с шифрованной схемы. Начинается с
нешифрованной, выкатывать нельзя: лечение не обход, а перевод на шифрование,
сертификат на виртуалке уже работает.

Датчики: разметка 0 ошибок, ссылки живые.
2026-08-07 08:14:19 +03:00
Дмитрий c2b3fe47fc docs: промт-передача следующей сессии по вкладке «Активность» 2026-08-07 08:12:50 +03:00
Дмитрий 0181f2e3e7 docs: промт-передача следующей сессии по вкладке «Активность»
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 08:12:36 +03:00
Дмитрий e4a4766c50 docs: план переделки вкладки «Активность» под вопрос «жив ли клиент» 2026-08-07 08:05:53 +03:00
Дмитрий 16d8191d08 docs: план переделки вкладки «Активность» под вопрос «жив ли клиент»
11 задач по TDD: два сервиса на бэкенде (вердикт с полоской и лента дел из
пяти источников), ручка подгрузки, живая сортировка списка клиентов, типы и
маппер, русские фразы, панель Vue, точка состояния в списке, полный прогон,
приёмка глазами.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 08:05:43 +03:00
Дмитрий 9247281688 fix поиск клиентов: дверь к рендер-виртуалке — разрешённые машины и обязательное шифрование, Р126
Тайный ключ SELF_RENDER_KEY уходил заголовком X-Render-Key на любой адрес, какой окажется
в настройке. Проверялось ровно одно: адрес не пуст и ключ не пуст. Отсюда две молчаливые беды:
опечатка в SELF_RENDER_ENDPOINT увела бы ключ чужому человеку навсегда и без признаков,
а http:// увёз бы его открытым текстом.

Дверь повторяет проверенное устройство Р123 от голосового робота: своя причина на пустой
адрес и на пустой ключ, список разрешённых машин с пустым списком как «закрыто всё»,
обязательное https кроме своей машины, а «своя машина» — два независимых ответа: окружение
из положительного списка И двоичная проверка петли 127.0.0.0/8, ::1, localhost по RFC 6761.
Закрытая дверь = мягкая деградация: наружу не ходим, отдаём пусто, причина в журнал уровнем
warning, потому что на боевом всё ниже не доезжает.

Тумблера «можно без шифра» нет намеренно: он и был бы той самой опечаткой.

Дыр было ДВЕ, а не одна. Тот же ключ и тот же SELF_RENDER_ENDPOINT уходят из
RenderServiceYandexListSource — лента Яндекс.Карт. Починка только названного файла оставила
бы дыру открытой, поэтому дверь общая на обе.

Боевой поиск не сломается: умолчание списка НЕ пустое и содержит замеренный боевой адрес
виртуалки 51-250-1-97.sslip.io — пустое умолчание остановило бы поиск в момент выката.
Набор тот же, что владелец уже принял для OBZVON_ALLOWED_HOSTS: это одна и та же машина.
Прогнаны все формы адреса, какие могут стоять в боевой настройке, в окружении production.

Проверок 37, сторожа показаны красными пятью отдельными сломами, возврат доказан слепками.
Larastan 0, Pint чисто.

Не закрыто и ждёт слова владельца: ProxyMarketProbe шлёт тот же ключ на другую настройку
без двери; боевое значение SELF_RENDER_ENDPOINT не замерено, на боевой не ходил.

Отчёт: docs/superpowers/priyomka/stroyka-6/otchyot-pomoshchnika-r126-dver-rendera-2026-08-07.md
2026-08-07 08:04:35 +03:00
Дмитрий 475e2d6245 docs обзвон: знак и тело больше не расходятся, промт смене 7 написан
Портальная причина дыры закрыта коммитом a4ff69aea. Помощник выбрал путь, где
портал считает опознавательный знак задания САМ внутри вызова, а наружу
принимает то, из чего знак складывается. Рассогласовать стало нечего.

Довод, которого не было в моём задании и который решил дело: второй путь всё
равно потребовал бы сменить подпись, потому что для сверки знак надо
пересчитать. То есть он платит ту же цену, а взамен даёт лишний довод, который
может быть только неверным, и новый исход дверь закрыта. А чем кончается
закрытая дверь? Человеку не позвонили. Второй путь не убирает вред, а делает его
громким.

Мой нож мерил не текст, а то, что вправду уезжает роботу. Один человек в двух
записях даёт один знак И одно тело. Строка без цифр закрывает дверь, наружу не
уходит ничего. Вторая попытка и другой клиент дают другой знак.

И мой нож замерил цену того, что помощник НЕ стал чинить осознанно: человек,
записанный восьмёркой и семёркой, считается двумя разными, и ему позвонят
дважды. Он нашёл это сам и вынес владельцу, потому что ошибка в обратную сторону
тише и хуже: слияние двух разных людей означало бы, что второму не позвонят
никогда и молча. Владелец закрыл это решением Р127: восьмёрку приводим к
семёрке только у одиннадцатизначных номеров.

Лучшая ошибка смены, названная помощником первой: его главный сторож был слеп
ровно к той половине беды, ради которой писался. Он сверял согласие с точностью
до приведения номера, а робот сравнивает тело дословно. Вернул беду в код,
сторож остался зелёным. Не сломай он свою починку руками, сдал бы работу с
дырявым главным сторожем.

Промт смене 7 написан: docs/superpowers/2026-08-10-PROMT-obzvon-stroyka-4.md.
В нём правила стройки вперёд всего, 57 ошибок надзирателя, 28 правил, числа
собраны командой, порядок работ и три ловушки, которые выглядят правильными.
В промте смены 6 поставлен указатель, что он отработан.

Датчики: задач 54, врезок ПОСТРОЕНО 19, требований 112, решений 127.
Разметка 0 ошибок, правописание протокола 0 жалоб, все ссылки промта ведут к
живым файлам.
2026-08-07 07:53:48 +03:00
Дмитрий b941be5067 docs приёмка: дефект М-1 выкачен на боевой и доказан живыми данными
Accessibility (Pa11y live) / a11y (push) Has been cancelled
SAST — Semgrep / Semgrep SAST scan (push) Has been cancelled
Задание 88 закончилось после выката и принесло ту же дату старта, а время
изменения кампании №15 осталось от прошлого задания. Раньше совпадало с концом
каждого задания до секунды — значит строку больше не трогают и счётчик 48 часов
пошёл по-настоящему.

Никого не стёрли: перепись боевого 1031 файл до и после, боевая копия файла до
выката побайтово равна прежней версии, после — новой.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 07:50:04 +03:00
Дмитрий 6b732de6ad fix телеграм: счётчик зависшей модерации сбрасывался каждой проверкой робота
Кампания, застрявшая на модерации дольше 48 часов, обязана уйти в ручной
разбор — иначе висит вечно с замороженными деньгами клиента и молча.
Срок считается по времени изменения строки, а вчерашняя правка «день начала
показов» писала дату при КАЖДОЙ проверке робота массовым обновлением, которое
всегда двигает updated_at. Робот ходит раз в четверть часа — счётчик не
досчитал бы никогда. Защита была цела на вид и мертва на деле.

Улика с боевого: у кампании №15 время изменения строки совпадало с концом
последнего задания робота до секунды, при том что вердикта не было третьи сутки.

Пишем дату, только если она вправду изменилась. Сравнение сырых значений мимо
приведения типов: starts_on это date:Y-m-d, сравнение с Carbon разошлось бы молча.

Сторожа SchyotchikZavisshejModeraciiTest (3 шт) видены красными до правки.
Блок телеграма 381 зелёный на своей базе, статанализ 0, pint чисто.
На боевой НЕ выкачено.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 07:50:01 +03:00
Дмитрий 2a05adfac9 @
fix: письма о недоливе — одна сводка в сутки вместо потока на каждом прогоне

Сверка с поставщиком шла каждые 30 минут и на каждом прогоне слала письмо
на КАЖДУЮ пару (тенант, дата) с недоливом больше 20%. Вчерашняя дата остаётся
в окне сверки, поэтому поток рос день ото дня: 144 письма 27.07 → 510 за 06.08,
около 3000 за 12 дней на ops@liderra.ru.

Теперь пары собираются в один список и уходят одной сводкой раз в сутки
(отсечка по московской дате в redis; гонки нет — handle держит общий lock).
Частоту самой сверки не трогал.

Поштучный TenantBusinessDriftAlertMail с шаблоном удалён — стал мёртвым.

Тесты: сводка собирает все пары в одно письмо, второй прогон в те же сутки
молчит, в новые сутки письмо уходит снова. Красными их видел.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@
2026-08-07 07:49:27 +03:00
Дмитрий c298789eef docs: спека переделки вкладки «Активность» под вопрос «жив ли клиент» 2026-08-07 07:49:07 +03:00
Дмитрий c9daf48bdc docs: спека переделки вкладки «Активность» под вопрос «жив ли клиент»
Замерено на боевом: вкладка читает журнал сделок, где 364 из 419 строк —
системные «робот залил лид». Данные про входы и про дела клиента лежат в
двух других журналах и на вкладку не попадают вовсе.

Решения владельца: вердикт + полоска 90 дней + лента только дел, пороги
3 и 14 суток, входы только сверху, заодно чиним мёртвую сортировку списка
клиентов по последней активности.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 07:48:57 +03:00
Дмитрий a4ff69aea3 fix обзвон: знак задания и номер в теле больше не могут разойтись
Портальный клиент голосового робота считал опознавательный знак задания от
ОДНИХ ЦИФР телефона, а в тело задания клал номер КАК ЕСТЬ. Один и тот же
человек, записанный `+7 999 000-00-01` и `79990000001`, давал ОДИН знак и
РАЗНЫЕ тела. Приёмник робота сравнивает тело дословно и на такую пару
отвечает отказом — то есть честный повтор получал отказ вместо звонка.

Вторая половина той же беды: знак и телефон приходили в `pozvonit` ДВУМЯ
независимыми доводами, и ничто не заставляло их сойтись. Работник очереди,
посчитавший знак один раз и перебирающий номера, отправил бы роботу
рассогласованную пару, и человеку не позвонили бы молча.

Что сделано:

- заведено ОДНО место приведения номера — `ObzvonClient::odinVidNomera`;
  оба потребителя берут номер оттуда: и знак, и тело задания;
- `pozvonit` больше НЕ принимает знак снаружи. Он принимает то, из чего знак
  складывается — арендатор, кампания, номер, попытка, — и складывает знак сам.
  Рассогласовать нечего: второго номера в клиенте не существует;
- отказ по номеру теперь считается по признаку "в номере ноль цифр", а не по
  `trim`. Раньше строка вроде "абв" проходила дальше и давала ОДИН И ТОТ ЖЕ
  знак на все такие задания — два разных задания столкнулись бы знаками у
  робота, и одному из людей не позвонили бы вовсе;
- в докблоке `pozvonit` вслух записано следствие решения владельца Р124:
  номер попытки нельзя прибавлять на исходе, где звонок МОГ состояться, —
  иначе знак станет другим и защита не сработает именно в том случае, ради
  которого заведена.

Разбор ответа робота, пределы времени, предел одновременных и проверка
шифрования Р123 не тронуты.

Мерки. Сторожа роняли работой, а не текстом: возвращали беду в код и
смотрели на то, что уходит подставному роботу.

- вернул в тело номер "как есть" — 4 красных из 55;
- вернул знак доводом снаружи — 1 красный из 55, сторож читает доводный ряд
  метода через `ReflectionMethod`, а не текст файла;
- возврат доказан слепком со снятием невидимых знаков конца строки,
  после возврата 55 из 55 зелёных;
- полный прогон на своей базе: 5293 проверки, 5289 зелёных, красных 0,
  ошибок 0, пропущено 4; арифметика сходится;
- `composer stan` — 0 ошибок, `pint --test` — passed.

Открытым оставлено и названо в отчёте: `8...` и `+7...` сегодня разные люди
для портала; `dopolnitelno` обязано быть одинаковым у повтора; правило счёта
попыток не назначено.

Отчёт: docs/superpowers/priyomka/stroyka-6/otchyot-pomoshchnika-znak-tela-2026-08-07.md
2026-08-07 07:43:34 +03:00
Дмитрий abe4a7e48b docs телеграм: снят неверный вывод о причине закрытия окна входа
Проверка на второй заход опровергла мой же разбор. На СТАРОМ коде служба
отступала пять раз подряд, пока окно владельца было открыто, и вернулась к
работе ровно в минуту закрытия — защита работала. Довод «в журнале нет ни
одной строки ПРОПУСК» был замером через полминуты после открытия окна:
пустой журнал доказывал лишь, что окно ещё не дожило до проверки.

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

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 07:42:51 +03:00
Дмитрий d844542c29 docs телеграм: вход в кабинет МТС восстановлен — служба лезла поверх окна владельца
Владелец не мог войти руками: окно закрывалось раньше, чем он успевал.
Защита службы «профиль занят» сравнивала путь буква в букву и искала обратные
косые черты, а браузер подписывается прямыми — совпадения не было никогда.
Улика: за всю жизнь службы в журнале ноль строк «ПРОПУСК: профиль занят».

Починка живёт вне git (C:\liderra\mts-telegram-robot): сравнение вынесено в
etoNashProfil под 5 сторожей, тесты робота 197 -> 202. Проверено живьём:
вход сохранён, сторож ALIVE, задание 52 ok=true, служба дважды отступила
при занятом профиле.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 07:42:49 +03:00
Дмитрий 4513fe1a58 docs приёмка: дефект М-1 выкачен на боевой и доказан живыми данными 2026-08-07 07:34:28 +03:00