ci(deploy): deploy-пользователь вместо root, DEPLOY_HOST в секретах; fix jsdom для Node 20
Шаг 0.3 плана production-готовности: - deploy.yml: username deploy, host из секрета DEPLOY_HOST - сервер: пользователь deploy (группа docker), /opt/crm переписан на deploy - SSH_KEY = ключ deploy (не root) - pr-check fix: jsdom ^26 (jsdom 30 несовместим с Node 20 CI-раннера)
This commit is contained in:
@@ -465,3 +465,36 @@
|
||||
- JWT детерминирован по (payload, iat в секундах): две ротации одной и той же сессии в пределах одной секунды выдадут одинаковый токен — безвредно (хэш и семантика совпадают).
|
||||
- `bot_sessions` (refresh-токены bot_login) сознательно не тронуты — отдельная модель audience `workflow-bots`; кандидат на аналогичное хэширование отдельным шагом. In-memory `resetTokenStore` суперадмина — не в БД, вне скоупа.
|
||||
- Удаление legacy plain-колонок — отдельная миграция после подтверждения стабильности на проде.
|
||||
|
||||
---
|
||||
|
||||
## [0.6] TTL access-токена 15m + хэширование refresh/reset-токенов
|
||||
|
||||
- Статус: ✅ done (коммит `06bfd2a`, ветка feat/token-security → main, окно подтверждено пользователем 2026-09-08)
|
||||
- Зачем: укоротить окно атаки при краже access-токена; токены в БД только в виде хэша.
|
||||
- Что изменено: дефолт JWT_ACCESS_EXPIRES 30d→15m (env сохранён); миграция 0082 (refresh_token_hash + parent/replaced_by хэши в user_sessions, reset_password_token_hash в users; очистка сессий = глобальный разлогин); выпуск/поиск/отзыв только по sha256-хэшу (server/utils/jwt.ts hashToken, users.storage.ts, auth.service.ts — rotateFamilySession, grace-ротация для гонки вкладок); resetPasswordTokenHash в исключениях SafeUser. Фронт не тронут — refresh реактивный по 401.
|
||||
- Как проверялось: 12 новых тестов (118/118); деплой на прод — сессии очищены миграцией (ожидаемо).
|
||||
- Проверка на проде: re-login работает, refresh-ротация (access 15 мин) — см. ниже в этой записи после подтверждения.
|
||||
- Влияние на поиск/UX: нет; пользователи перелогинились один раз.
|
||||
- Подводные камни: bot_sessions не хэшированы (отдельная audience-модель, отложено); legacy plain-колонки удалить отдельной миграцией после стабилизации.
|
||||
|
||||
## [0.3] Не-root deploy-пользователь
|
||||
|
||||
- Статус: ✅ done
|
||||
- Зачем: убрать постоянный root-SSH из CI.
|
||||
- Что изменено:
|
||||
- Сервер: пользователь `deploy` (uid 1000, группа docker), SSH-ключ `github-actions-deploy` (сгенерирован локально, публичный — в authorized_keys deploy, приватный — в секрет SSH_KEY через GitHub API, локальная копия `.ssh/deploy_ci` вне репо).
|
||||
- `/opt/crm` переписан на deploy:deploy; бэкап compose доступен на чтение.
|
||||
- `.github/workflows/deploy.yml`: `username: deploy`, хост — секрет `DEPLOY_HOST` (вместо хардкода).
|
||||
- PermitRootLogin — будет выставлен в prohibit-password после подтверждения, что деплой от deploy работает (ниже).
|
||||
- Как проверялось: SSH от deploy + docker ps — OK; su deploy git status в /opt/crm — OK; деплой от deploy — после пуша этого коммита.
|
||||
- Влияние на поиск/UX: нет.
|
||||
- Подводные камни: на сервере остался UU-конфликт в index (последствие stash pop), чистится в 0.14; root-SSH пока остаётся как fallback до подтверждения.
|
||||
|
||||
## CI: фикс pr-check (jsdom для Node 20)
|
||||
|
||||
- Статус: ✅ done
|
||||
- Зачем: pr-check падал с 06bfd2a (и 639036c): vitest не стартовал a11y-файл — `webidl.util.markAsUncloneable is not a function` в undici: jsdom@30 несовместим с Node 20 раннера (локально Node 24 — работало).
|
||||
- Что изменено: jsdom 30 → ^26 (devDependencies).
|
||||
- Как проверялось: vitest 118/118 локально; pr-check на этом коммите.
|
||||
- Подводные камни: CI = Node 20, локаль = Node 24 — расхождение учитывать при добавлении тестовых зависимостей.
|
||||
|
||||
Reference in New Issue
Block a user