architect/standards/arch-security-policy.md

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 КОНФИДЕНЦИАЛЬНОСТЬ для трёх зон:

Уровень Зона Угроза
С1 CREDENTIALS Секреты, ключи, пароли Утечка / компрометация
С2 BACKUP Данные и конфигурации Потеря / уничтожение
С3 ROLLBACK Изменения кода и инфры Сбой деплоя / регрессия
extends: PolicyConfidentiality    П1 из arch-platform-policy.md

Нарушение любого уровня → СТОП → уведомление оператора → логирование в system/monitor/alerts/.


2. С1: CREDENTIALS

Секреты, 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
❌  передавать ключи агенту через сообщение

Если credentials попали в git

# 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. немедленно ротировать скомпрометированные ключи

Система хранения секретов (BACKLOG)

Текущее состояние: секреты в .env файлах на сервере.
Целевое состояние: system/@vault.service/ — HashiCorp Vault в Docker.
Статус: 🔴 CRITICAL в BACKLOG.md.


3. С2: BACKUP

Резервное копирование данных и конфигураций.

Что бэкапить

Объект Частота Хранение Путь
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)
⚠️  Бэкапы на том же сервере — не защита от потери сервера

4. С3: ОТКАТ

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

Три метода отката

Метод Когда Скорость
git revert изменение кода/документов ~5 мин
Docker образ предыдущей версии сбой деплоя сервиса ~10 мин
Восстановление из бэкапа критическая потеря данных ~30-60 мин

Git откат

# откат последнего коммита (сохранить изменения)
git revert HEAD

# откат к конкретному коммиту
git revert <commit-hash>

# ЗАПРЕЩЕНО: git reset --hard в main без явного "да" оператора

Перед откатом:

git log --oneline -10          # найти точку возврата
git stash                      # сохранить незакоммиченное

Docker откат

# пометить образ перед деплоем
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

5. СВЯЗАННЫЕ ДОКУМЕНТЫ