type: standard
layer: arch
object: security
aspect: policy
form: text
title: "Политика безопасности"
status: active
version: 1.0.0
date: 2026-04-11
knowledge_level: У1
parent: arch-platform-policy.md
deps:
- arch-platform-policy.md
- arch-filesystem-structure.md
- arch-document-format.md
Стандарт определяет три уровня безопасности платформы: С1 CREDENTIALS (секреты и ключи), С2 BACKUP (резервное копирование), С3 ROLLBACK (откат изменений). Наследует П1 КОНФИДЕНЦИАЛЬНОСТЬ из arch-platform-policy.md.
Политика безопасности конкретизирует П1 КОНФИДЕНЦИАЛЬНОСТЬ для трёх зон:
| Уровень | Зона | Угроза |
|---|---|---|
| С1 CREDENTIALS | Секреты, ключи, пароли | Утечка / компрометация |
| С2 BACKUP | Данные и конфигурации | Потеря / уничтожение |
| С3 ROLLBACK | Изменения кода и инфры | Сбой деплоя / регрессия |
extends: PolicyConfidentiality ← П1 из arch-platform-policy.md
Нарушение любого уровня → СТОП → уведомление оператора → логирование в system/monitor/alerts/.
Секреты, API-ключи, пароли, токены — ни в git, ни в чат, ни в логи.
| Тип | Где хранить | Формат |
|---|---|---|
| Переменные окружения | .env в $DATASPACE |
KEY=value |
| API-ключи сервисов | .env рядом с docker-compose.yml (не в git) |
SERVICE_API_KEY=... |
| SSH-ключи | ~/.ssh/ на сервере |
стандартные права 600 |
| Системные пароли | только в голове оператора | — |
В git — только .env.example без значений:
# .env.example
TELEGRAM_BOT_TOKEN=
OZON_API_KEY=
DB_PASSWORD=
❌ echo $API_KEY в чате
❌ git add .env
❌ пароль в комментарии кода
❌ credentials в CLAUDE.md / AI.md / README.md
❌ передавать ключи агенту через сообщение
# 1. удалить из истории
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch .env" \
--prune-empty --tag-name-filter cat -- --all
# 2. force push (L4 — только после явного "да" оператора)
git push origin --force --all
# 3. немедленно ротировать скомпрометированные ключи
Текущее состояние: секреты в .env файлах на сервере.
Целевое состояние: system/@vault.service/ — HashiCorp Vault в Docker.
Статус: 🔴 CRITICAL в BACKLOG.md.
Резервное копирование данных и конфигураций.
| Объект | Частота | Хранение | Путь |
|---|---|---|---|
| PostgreSQL (все БД) | ежедневно 03:00 | 30 дней | $DATASPACE/backups/db/ |
| $WORKSPACE (git-репо) | при каждом пуше | всегда | удалённый git + S3 |
| Docker volumes с данными | ежедневно 04:00 | 14 дней | $DATASPACE/backups/volumes/ |
| .env файлы | при изменении | 90 дней | $DATASPACE/backups/env/ |
| Nginx конфиги | при изменении | 90 дней | $DATASPACE/backups/nginx/ |
YYYYMMDD_HHmm_{тип}_{объект}.{ext}
20260411_0300_db_nocodb.sql.gz
20260411_0400_vol_lideravto-data.tar.gz
20260411_1530_env_infra.tar.gz.enc ← зашифровано
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M)
BACKUP_DIR="$DATASPACE/backups/db"
pg_dumpall -U postgres | gzip > "$BACKUP_DIR/${DATE}_db_all.sql.gz"
# удалить старше 30 дней
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +30 -delete
# проверить последний дамп
gunzip -t $DATASPACE/backups/db/$(ls -t $DATASPACE/backups/db/ | head -1)
echo "Exit code: $?" # 0 = OK
# проверить размер (не нулевой)
ls -lh $DATASPACE/backups/db/ | tail -5
⚠️ Бэкап без проверки восстановления = не бэкап
⚠️ .env файлы бэкапить зашифрованными (gpg или openssl)
⚠️ Бэкапы на том же сервере — не защита от потери сервера
Процедура восстановления предыдущего состояния при сбое деплоя, миграции или критической ошибки.
| Метод | Когда | Скорость |
|---|---|---|
git revert |
изменение кода/документов | ~5 мин |
| Docker образ предыдущей версии | сбой деплоя сервиса | ~10 мин |
| Восстановление из бэкапа | критическая потеря данных | ~30-60 мин |
# откат последнего коммита (сохранить изменения)
git revert HEAD
# откат к конкретному коммиту
git revert <commit-hash>
# ЗАПРЕЩЕНО: git reset --hard в main без явного "да" оператора
Перед откатом:
git log --oneline -10 # найти точку возврата
git stash # сохранить незакоммиченное
# пометить образ перед деплоем
docker tag {service}:latest {service}:backup-$(date +%Y%m%d)
# откат
cd infra/@{имя}.service/
docker compose down
docker tag {service}:backup-YYYYMMDD {service}:latest
docker compose up -d
# 1. остановить сервис
docker compose stop app
# 2. восстановить из дампа
pg_restore -U $DB_USER -d $DB_NAME \
$DATASPACE/backups/db/YYYYMMDD_HHmm_db_all.sql.gz
# 3. проверить
psql -U $DB_USER -d $DB_NAME -c "SELECT COUNT(*) FROM key_table;"
# 4. запустить
docker compose start app
1. СТОП — прекратить все изменения
2. ОЦЕНИТЬ — что сломалось: код / данные / оба?
3. УВЕДОМИТЬ оператора
4. ОТКАТИТЬ — выбрать метод (git/docker/restore)
5. ПРОВЕРИТЬ — сервис отвечает, данные целы
6. ЗАФИКСИРОВАТЬ — что пошло не так → system/monitor/alerts/
# сервис
docker compose ps
curl -s -o /dev/null -w "%{http_code}" http://localhost:{port}/health
# данные
psql -c "SELECT COUNT(*) FROM critical_table;"
# логи
docker compose logs --tail=50 app