7.5 KiB
7.5 KiB
Архитектура VK Giveaway Randomizer
1. Обзор архитектуры
Система построена по принципам чистой архитектуры (Clean Architecture / Hexagonal Architecture) с разделением на независимые слои:
graph TD
UI[Frontend UI: Next.js App Router] --> API[Next.js API Routes / Server Actions]
API --> Core[Core Domain Layer: Randomizer & Filtering]
API --> Providers[Social Providers Layer: VK / Telegram / YouTube]
API --> DB[(Database: PostgreSQL + Prisma)]
Providers --> VK[Official VK API / VK Mock]
2. Слои приложения
2.1. Core Domain Layer (src/core/)
Ядро приложения не зависит от конкретной социальной сети или веб-фреймворка:
src/core/randomizer/:deterministic.ts: Реализация детерминированного генератора случайных чисел (PRNG) и перетасовки Фишера-Йетса с использованием криптографических хешей (SHA-256 HMAC).hasher.ts: Генерация фиксированного отпечатка (Snapshot Hash) списка участников перед розыгрышем.
src/core/filtering/:filter-engine.ts: Механизм фильтрации участников на основе заданных условий (лайк, репост, коммент, подписка, черный список ID, исключение админов, дедупликация).
src/core/types/:- Типизированные контракты сущностей (
Giveaway,Participant,DrawResult,AuditRecord,FilterRules).
- Типизированные контракты сущностей (
2.2. Social Providers Layer (src/providers/)
Абстракция взаимодействия с внешними платформами:
SocialMediaProvider(Interface):fetchPost(url: string): Получение метаданных публикации (автор, текст, превью, счетчики).fetchParticipants(params: FetchParticipantsParams): Загрузка списка участников (лайки, комменты, репосты).checkSubscription(userIds: string[], groupId: string): Проверка подписки на сообщество.
VkProvider: Боевой клиент к VK API с поддержкой пакетных запросовexecute.VkMockProvider: Тестовый провайдер для демонстрации, локальной разработки и оффлайн-тестирования.ProviderRegistry: Фабрика для получения провайдера по типу платформы (vk,telegram,youtube).
2.3. Data & Persistence Layer (prisma/ + src/lib/)
- PostgreSQL в качестве надежного реляционного хранилища.
- Prisma ORM для типобезопасной работы с БД.
- Хранение всех розыгрышей, снапшотов участников и записей аудита для публичной верификации.
2.4. Presentation Layer (src/app/ + src/components/)
- Modern React + Next.js App Router.
- Интерактивный визард создания розыгрыша с живым превью поста, настройкой условий, интерактивной таблицей участников и презентацией победителей.
3. Механизм честности и доказуемости (Provably Fair)
Каждый розыгрыш формирует криптографический аудит-след на базе алгоритма HMAC_SHA256_FY_V1:
- Снапшот участников: Список прошедших фильтрацию (eligible) участников сортируется по
platformUserIdи канонически сериализуется:\text{ParticipantsSnapshotHash} = \text{SHA256}(\text{canonicalStringify}(\text{sortedEligibleParticipants})) - Seed Pre-Commitment (Защита от Seed Grinding):
- В момент фиксации слепка (
SNAPSHOT_LOCKED) сервер генерирует CSPRNG seed и публикует его SHA-256 обязательство:\text{SeedCommitment} = \text{SHA256}(\text{seed}) - До момента проведения жеребьевки сам
seedстрого скрыт (seed: null), ноseedCommitmentдоступен публично. Организатор может зафиксировать его публично (например, в комментарии к конкурсному посту VK) до розыгрыша.
- В момент фиксации слепка (
- Детерминированный выбор (
HMAC_SHA256_FY_V1):- Выборка осуществляется с помощью несмещенного сэмплинга Фишера-Йетса (Fisher-Yates) поверх потока псевдослучайных байт HMAC-SHA256:
\text{ByteStream} = \text{HMAC-SHA256}(\text{key} = \text{seed}, \text{data} = \text{ParticipantsSnapshotHash} \parallel \text{ConditionsHash} \parallel \text{blockIndex}) - Позиции победителей и резерва рассчитываются детерминированно.
- Выборка осуществляется с помощью несмещенного сэмплинга Фишера-Йетса (Fisher-Yates) поверх потока псевдослучайных байт HMAC-SHA256:
- Публичное раскрытие и аудит:
- После перевода розыгрыша в статус
DRAWNсервер раскрываетseed. - Любой участник может проверить:
\text{SHA256}(\text{seed}) == \text{SeedCommitment}(гарантия того, что seed не подбирался под желаемого победителя);- Воспроизведение результатов выборки при наличии слепка;
- Неизменность
deterministicProofHashиauditEventHash.
- После перевода розыгрыша в статус
3.1. Границы публичной проверяемости и защита приватности (PII Compromise)
- Что проверяется внешним наблюдателем:
- Корректность раскрытия seed относительно опубликованного pre-commitment.
- Математическая повторяемость алгоритма.
- Совпадение хешей доказательства (
deterministicProofHash).
- Что остаётся приватным:
- Полный список участников и их персональные данные (PII) не отдаются анонимным пользователям в целях соблюдения требований защиты данных третьих лиц. Публикуются только победители и хеш слепка
participantsSnapshotHash. - Внешний наблюдатель без исходного списка участников не может самостоятельно с нуля пересчитать
participantsSnapshotHash.
- Полный список участников и их персональные данные (PII) не отдаются анонимным пользователям в целях соблюдения требований защиты данных третьих лиц. Публикуются только победители и хеш слепка
- Архитектурный статус доверия:
- Доказательство формируется и проверяется на сервере Randomayzer на основе зафиксированного в БД слепка. Децентрализованный внешний якорь (блокчейн, drand, RFC 3161) на текущем этапе не используется.