# PRD — md2vk (публикация Markdown в VK) ## Цель Сервис для публикации статей в формате Markdown на стену VK (личную или сообщества) через официальный VK API (wall.post + format_data). Конвертация Markdown → VK-разметка, шифрование токенов, архив публикаций. ## Пользователи - Лично (estorozhenko) — публикация статей на стены VK. ## Функциональные требования - [x] Конвертация Markdown → VK format_data (жирный, курсив, код, ссылки, заголовки, цитаты, блоки кода) - [x] Публикация поста на стене VK (wall.post) с VK-токеном - [x] Управление VK-аккаунтами (добавить, список, удалить) — ручной ввод access_token (Phase 1) - [x] Архив публикаций с фильтрацией (Publication) - [x] Конвертация без публикации (preview) - [x] Аутентификация по API-ключу (заголовок Authorization: Bearer + тело api_key) - [x] Шифрование VK-токенов (Fernet, AES-128-CBC + HMAC-SHA256) - [x] Аудит-лог всех /api/v1/* (JSONL, ротация по дням) - [ ] OAuth-флоу VK ID (нужны client_id/secret VK-приложения) — открытая задача - [ ] Планировщик отложенных постов (status=scheduled → wall.post) — открытая задача - [ ] Web UI (форма поста + превью) — открытая задача ## Нефункциональные требования - [x] HTTPS наружу (Caddy на vps02 + Let's Encrypt), basic_auth (пользователь estorozhenko, bcrypt) - [x] Защита от брутфорса: fail2ban на vps02, ban после 5 неудачных попыток (bantime=-1, ручной unban) - [x] Слушает ТОЛЬКО на WG-интерфейсе 10.8.0.2:8420 (наружу не доступен, кроме Caddy) - [x] БД и логи — bind-mount на хосте (вне контейнера) - [x] Контейнер read_only: true (кроме /data и /logs) - [x] Rate limiting: RATE_LIMIT_PER_MINUTE=10 в конфиге (in-memory bucket НЕ реализован — открытая задача) - [ ] Graceful shutdown, retry при сетевых ошибках VK API — открытые задачи ## Границы (что НЕ делаем в Phase 1) - НЕ «взламываем» VK: только официальный OAuth 2.0 / VK API - Лонгриды/статьи через API не публикуются (только wall.post с анонсами/ссылками) — ограничение VK API - Планировщик отложенных постов не включается в текущую итерацию - Полный OAuth-флоу — отдельная задача (после получения client_id/secret) ## Критерии готовности - [x] Сквозная проверка: https + auth (401/200) + ban после 5 попыток + ручной unban - [x] Pull mirror gitverse → gitea синхронизирован - [x] Документация в docs/ (index, access, architecture, vk-api, security, deploy, status) + AGENTS.md - [x] openspec baseline зафиксирован ## Доступы (реквизиты) - Домен: https://md2vk.nixg.ru (vps02, Caddy) - Пользователь basic_auth: estorozhenko (bcrypt-хэш в Caddyfile, пароль НЕ в git) - Backend: bigbox 10.8.0.2:8420 (WG) - Git: gitverse.ru/kpa39l/md2vk (primary) → gitea.nixg.ru/estorozhenko/md2vk (pull mirror, 8h) - openspec: /opt/md2vk/openspec/