# CORP: исправления по диагностике 10 сентября 2026 ## Состав изменений - Исправлены блокировки PostgreSQL для подтверждения выплат, переноса зарплаты, создания оборудования и автоматизаций задач. Проверки используют PostgreSQL, а не только SQLite. Рабочие финансовые записи вручную не изменяются. - В requirements закреплён WebSocket-транспорт `wsproto`. Деплой проверяет зависимости, настоящий WebSocket upgrade/обмен кадром и отказ анонимному подключению до переключения трафика. - Исправлены структурированные журналы: маскирование OAuth/WS-параметров, сохранение начала и конца длинной трассировки, доверенные прокси для IP. Nginx access log не записывает query string и Referer. - Уточнены OpenAPI-контракты; конфигурация push_notifications согласована с AutoField в поставляемых миграциях без изменения таблиц. - Исторические миграции django_fsm проверены с поддерживаемым django-fsm-2. - Для коротких аббревиатур, отбрасываемых PostgreSQL как стоп-слова, добавлен ограниченный поиск по целому токену заголовка с прежними проверками доступа. - Файлы документов выдаются через API с проверкой ACL; приватные загрузки не предоставляют прямой Filer URL. Frontend передаёт авторизацию при загрузке. - Вложения заявлений и чатов переведены на проверяемую выдачу. Для временных вложений чата добавляется nullable-владелец: новые загрузки можно присоединять только от своего имени; старые незавершённые загрузки без владельца нужно загрузить повторно. Готовые сообщения и их файлы сохраняются. - Пересылка сообщения проверяет доступ к исходному чату, а изменение сообщения — право использовать каждое присоединяемое вложение. Списки сообщений фильтруются по действующим правам до пагинации, включая отозванное членство. - Очистка временных файлов повторно проверяет отсутствие привязки под блокировкой строки: параллельное присоединение файла к сообщению не приводит к его удалению. Удаление файла и миниатюры происходит только после фиксации транзакции. ## Системная конфигурация Внешний адрес остаётся `https://corp.robotail.pro`. Сертификат и его обновление обслуживает Synology. Внутренний маршрут: Synology `172.11.1.254` → HTTP `172.11.0.11:80`. Приложение на этом порту доступно только NAS и loopback; устаревший TLS listener CORP отключён. Внутренний участок не зашифрован: его безопасность зависит от доверенной сети и сетевых ограничений. `ops/security/install-corp-proxy-security.py` проверяет ожидаемую структуру Nginx, создаёт резервные копии и проверяет конфигурацию перед reload. Флаг `--protect-media` применяется **после** релиза frontend/backend с защищённой выдачей файлов. До этого блокировка raw URL сломала бы старые клиенты. Redis: AOF `everysec`, лимит 256 MiB, политика `noeviction`. При достижении лимита новые записи могут быть отклонены: это защита памяти, не гарантия доставки очередей. Перед применением проверяются использование памяти, дисковый запас и готовность AOF; ошибки вызывают попытку полного отката. На CORP установлен ImageMagick из репозитория Ubuntu: он требуется уже существующему ограниченному преобразованию больших изображений. Его отсутствие теперь обнаруживается до сборки релиза. Обновление остальных системных пакетов и автоматическое удаление пакетов не выполнялись. Journald ограничен 512 MiB/14 днями и резервом 2 GiB. Старые имена Celery log-файлов добавлены в logrotate. Эти ограничения дополняют, а не заменяют, дисковые проверки сборки, очистку неудачных релизов и хранение двух успешных. ## Runner и деплой Runner остаётся **глобальным** по решению владельца. Контейнер работает как непривилегированный UID 10001, без Docker socket/capabilities, с read-only корневой ФС и ограниченными временными каталогами. SSH-доступ к CORP ограничен forced command и актуальным SHA master; сервер Gitea проверяется по закреплённому SSH host key. URL источника и Git hooks нельзя незаметно подменить конфигом. UID 10001 имеет настоящую запись пользователя `runner` в производном образе; перед заменой контейнера отдельно проверяется OpenSSH без сети и ключей. Для frontend требуется Node.js 22.13+ (22.x) или 24.x LTS, проверка выполняется до создания кандидата. `npm ci` использует строгую проверку engines и повторяет только сетевые сбои: максимум три попытки под общим таймаутом и контролем диска. Ошибки зависимостей и postinstall не маскируются повторными попытками. В новой Python-venv закреплён pip 26.2.1 с проверкой SHA-256 bootstrap-wheel и ограниченной докачкой оборванных загрузок. Несовпадение хешей по-прежнему останавливает установку; активная venv и системный pip не обновляются. Остановка Gunicorn использует SIGTERM и достаточный таймаут мягкого завершения. Код 143 Next.js при штатной остановке не считается аварией. Telegram-транспорт и его fallback-механизмы сохранены; ссылка использует номер запуска Gitea. **Граница доверия:** глобальный `deploy:host` не изолирует авторов репозиториев друг от друга. Все имеющие право менять workflow должны быть доверенными. Для недоверенных проектов нужны отдельные одноразовые среды исполнения. Перед обновлением контейнера следует приостановить выдачу заданий и дождаться простоя; одного снимка списка процессов недостаточно. ## Ротация ключа Django Префикс `django-insecure-` вызывает предупреждение, но сам по себе не доказывает утечку или слабую случайность. `ops/security/rotate-django-key.py` предназначен для плановой ротации после выкладки поддержки `SECRET_KEY_FALLBACKS` и отдельного `JWT_SIGNING_KEY`. Старые JWT и ключ шифрования интеграций сохраняются, чтобы не оборвать сессии и не потерять доступ к сохранённым учётным данным. Новый ключ начинает действовать при следующем штатном деплое. Старый fallback удаляется после максимального срока старых сессий/password-reset подписей; безопасность при подтверждённой компрометации требует отдельного немедленного отзыва, а не сохранения старых подписей. ## Что требует отдельной инфраструктурной проверки - Зависание `jbd2` более 122 секунд и watchdog journald утром 10 сентября: нужен журнал Hyper-V и хранилища. Текущая нормальная нагрузка не объясняет исторический сбой и не доказывает его устранение. - Ранние рестарты Gitea совпадали с недоступностью PostgreSQL при загрузке; сама Gitea позднее работала стабильно. Необходима проверка порядка готовности ВМ/БД на гипервизоре. - Проверка каталогов и чтения архивов pg_dump не равна полноценной репетиции восстановления. Резервирование приложения/медиа и восстановление всей системы должны быть проверены отдельно в изолированной среде. Это устранение найденных дефектов и усиление защиты, не доказательство отсутствия всех возможных уязвимостей во всём приложении и инфраструктуре.