- README.md и README.en.md: что это, статус, скриншоты, быстрый старт в Docker,
установка без Docker, переменные окружения, схема, развёртывание, разработка;
- docs/architecture.md (модели, оценки без регистрации, антинакрутка, безопасность)
и docs/deploy.md (Docker и устройство боевого сервера) вместо описания моделей в README;
- файл LICENSE (MIT), который раньше был заявлен только в README.
populate_demo падала на импорте несуществующей ArticleCategory, строковых статусах
проектов и удалённом поле is_featured; теперь создаёт статусы проектов и работает,
это проверяет тест. load_initial_data была загрузчиком старой версии резюме под
прежние модели и тоже не запускалась — актуальный контент живёт в админке.
Образ публикуется в GitHub Packages (ghcr.io/edeev/deev.space) и в реестр
dcr.deev.su/edeev/deev.space (учётные данные — секреты ZOT_USERNAME/ZOT_PASSWORD).
- Dockerfile: collectstatic при сборке, gunicorn, непривилегированный пользователь,
база и загрузки в томе /data, миграции при старте;
- compose.yaml для запуска одной командой, .env.example со всеми переменными.
Без загруженного фото владельца страница падала с 500 (в манифесте статики нет
images/hero.png). Теперь используется static/img/hero.jpg; добавлен тест, который
проверяет, что все {% static %} в шаблонах указывают на существующие файлы.
33 теста на pytest-django в боевом режиме (DEBUG=False, настройки dspace/settings_test.py):
лайки и дизлайки анонимов, лимит оценок с одного IP, очистка HTML в
комментариях и форме обратной связи, капча, экранирование бейджей и постов в Telegram,
проверка адресов превью, уникальные просмотры и фильтр ботов, cookie посетителя.
- render_tech_badge: format_html вместо mark_safe с непроверенной подстановкой (XSS);
- превью ссылок статьи: только публичные http(s)-адреса, без запросов во внутреннюю
сеть сервера (SSRF); ошибки логируются вместо except: pass;
- автопостинг в Telegram переведён на parse_mode=HTML с html.escape (раньше в канал
уходили видимые обратные слэши), включается переменной SOCIAL_AUTOPOST;
- убран ping Google (эндпоинт отключён в 2023 году);
- ошибка отправки письма с формы обратной связи больше не глушится;
- whitenoise и DJANGO_SERVE_MEDIA для запуска без nginx;
- импорты упорядочены, неиспользуемые удалены (ruff).
Перенесено всё, что накопилось на сервере с декабря 2025:
- анонимный посетитель по подписанной cookie (main/middleware.py), лайки и дизлайки
без регистрации с антинакруткой, уникальные просмотры статей;
- карточка-паспорт, стек в одну строку, блок «В цифрах»;
- миграции 0005–0008, команды load_initial_data и populate_demo, robots.txt;
- обновлённые шаблоны, стили и скрипты.
Безопасность и порядок:
- все секреты только из окружения, значения по умолчанию пустые;
- DEBUG по умолчанию выключен, без DJANGO_SECRET_KEY запуск в бою невозможен;
- ALLOWED_HOSTS, путь к базе и SSL-редирект настраиваются переменными;
- убрана статика админки Django (результат collectstatic) и media из git;
- добавлены .gitignore и .gitattributes (переводы строк — LF).