Indexium/todo.md

13 KiB
Raw Blame History

Indexium - TODO / Roadmap

Сервис: асинхронный событийный индексатор модов Minecraft поверх GitHub Releases CDN. Бэкенд не хранит тяжёлые артефакты, только метаданные + индексация + быстрый JSON API.


Правила проекта (обязательно к соблюдению)

Эти правила - не чекбоксы, а инварианты. Любой PR, нарушающий их, не принимается.

1. KISS - Keep It Simple, Stupid

  • Выбирай самое простое решение, которое закрывает задачу. Никаких абстракций «на будущее» (YAGNI).
  • Один модуль - одна ответственность. Если не можешь объяснить функцию в одном предложении - дроби.
  • Предпочитай явный код неявной магии (никаких макросов ради макросов).

2. DRY - Don't Repeat Yourself

  • Повтор >2 раз → выноси в функцию/модуль. Но не DRY ради DRY: дублирование лучше неправильной абстракции.
  • Общие типы/утилиты - в common/shared, доменная логика - в своём модуле.

3. SOLID (применительно к Rust)

  • S - один файл/модуль = одна причина для изменений (см. лимиты ниже).
  • O - открыт для расширения через трейты, закрыт для модификации (feature-flag, а не if на типы).
  • L - любой impl Trait должен заменять другой без поломки контракта.
  • I - узкие трейты лучше жирных (Readable, Validatable вместо GodService).
  • D - зависимость от абстракций (PgPool через AppState, а не глобаль).

4. Лимиты структуры (жёстко)

  • Макс 250 строк на файл - если больше, дроби файл на подмодули.
  • Макс 4 файла на папку - если больше, вводи подпапки по домену (api/mods/, worker/parsers/).
  • Исключение: mod.rs/lib.rs не считаются, но должны быть тонкими реэкспортами.
  • CI будет ругаться (cargo clippy + кастомный скрипт scripts/check-limits.sh).

5. Дополнительные инварианты

  • Чистота ошибок: никаких unwrap()/expect() вне main.rs и тестов. Везде Result + thiserror/anyhow.
  • Типы вместо строк: Slug, GameVersion, Loader - newtype, а не String.
  • Миграции только вперёд: никаких DROP без ADR и бэкапа. Каждая миграция - идемпотентна (IF NOT EXISTS).
  • Логика без сайд-эффектов: парсеры/валидаторы - чистые функции, I/O только на границах (handler/worker).
  • Документация рядом с кодом: публичная функция без /// - не готова к мерджу.
  • Тест на каждый баг: регрессия покрывается тестом до фикса.
  • Типографика: запрещено использование em dash (U+2014). Везде используй - (дефис). Проверка: scripts/check-no-emdash.sh должен быть OK.

Легенда статусов

  • [ ] - не начато
  • [~] - в процессе
  • [x] - готово
  • [!] - заблокировано / требует решения

Phase 0 - Фундамент монорепо (Текущий приоритет)

  • Объединить indexium-backend + indexium-frontend в один git-монорепо (корень /)
  • Настроить корневой .gitignore + локальные .gitignore
  • Создать структуру docs/ и заполнить базовую архитектуру
  • Создать todo.md и README.md в корне + прописать правила KISS/DRY/SOLID и лимиты файлов
  • Первая миграция 20260906000000_init_schema.sql (mods, mod_versions, GIN индексы)
  • Базовый src/main.rs (Axum + SQLx + CORS + /health + миграции при старте)
  • Настройка .env / .env.example (DATABASE_URL, SERVER_PORT)
  • Добавить docker-compose.yml (Postgres + Redis/Valkey) для локальной разработки
  • Добавить Makefile / justfile с командами dev, migrate, lint, test
  • Настроить CI (GitHub Actions): cargo clippy + test, svelte-check, sqlx migrate check
  • Скрипт scripts/check-limits.sh - проверка 250 строк / 4 файла на папку

Phase 1 - Backend Core (Rust / Axum)

1.1 Инфраструктура

  • config - загрузка .env (DATABASE_URL, REDIS_URL, GITHUB_APP_ID, WEBHOOK_SECRET) - база в main.rs через dotenvy
  • db - пул sqlx::PgPool, миграции (sqlx::migrate!), health-check /health
  • tracing - структурированные логи (EnvFilter + fmt layer)
  • Axum роутер: GET /health, CORS (5173), TraceLayer

1.2 Схема БД (PostgreSQL + FTS + pg_trgm)

  • Миграция 20260906000000_init_schema.sql - таблицы mods, mod_versions + GIN (game_versions, loaders)
  • Миграция 002_fts - search_vector, pg_trgm, триггер (см. docs/database-schema.md)
  • Таблица authors + webhook_deliveries (идемпотентность)
  • Сиды / фикстуры для локального дев-окружения

1.3 Webhook Ingestion API

  • POST /api/v1/webhooks/github - проверка X-Hub-Signature-256 (HMAC SHA-256)
  • Валидация эвента release.published / release.released, идемпотентность по delivery_id
  • Пуш задачи в очередь (Redis Streams) + ответ 202 Accepted < 50ms
  • Тест на replay-атаку и неверную подпись

1.4 Async Worker / Indexer

  • Консьюмер очереди (tokio task)
  • Скачивание через HTTP Range Request - чтение только ZIP central directory .jar
  • Парсинг fabric.mod.json / quilt.mod.json / neoforge.mods.toml / mcmod.info
  • Валидация: mod_id, version, game_versions, loaders, иконка
  • SHA-256 сверка (если приложен .sha256), отбраковка битого артефакта
  • Бейсик malware-скан: поиск Runtime.exec, URLClassLoader, сетевых вызовов в <clinit>
  • Сохранение в mod_versions, инвалидация Redis-кэша

1.5 Public REST API (Read-Heavy, Cache-First)

  • GET /api/v1/mods?query=&gameVersion=&loader=&page=&limit= - FTS + фильтры, кэш Redis 60s
  • GET /api/v1/mods/:slug - карточка мода + список версий
  • GET /api/v1/mods/:slug/versions/:version - детали версии + download_url (прямая CDN ссылка GitHub)
  • Пагинация cursor/offset, ETag, Cache-Control
  • Rate limiting (tower_governor / redis-cell)

1.6 Auth & Profiles (см. docs/auth-profiles.md, adr/004)

  • GitHub OAuth 2.0 (read:user, user:email) + JWT httpOnly - вход для авторов (MVP)
  • PAT personal_access_tokens (hash, scopes, expires) - POST /auth/tokens для CLI/лаунчеров (MVP)
  • POST /api/v1/mods/import - импорт репозитория (проверка LICENSE + public + манифест)
  • Профили /u/:login, /org/:login - кэш ISR, sponsors, verified badge, SVG /v1/badges/:slug/*.svg (MVP)
  • Star/Follow stars, follows (с фильтром game_version/loader) - in-app уведомления (MVP-лайт)
  • Device Flow RFC8628 (/oauth/device/code → /activate) - спроектировать, реализация Phase 2
  • Discord linked_accounts + бот роли Verified Modder - Phase 2
  • Установка Webhook'а через GitHub App API (автоматически) - миграция с OAuth на App в Phase 2

Phase 2 - Frontend (SvelteKit) + Social

  • Дизайн-система: Tailwind / UnoCSS + токены
  • Страницы: / (поиск + фильтры), /mod/[slug], /mods/import, /u/[login], /org/[login], /activate (device flow)
  • Компоненты: ModCard, VersionTable, SearchBar, LoaderBadge, ProfileHeader, SponsorsBar
  • Клиент API (src/lib/api.ts) - типизированные fetch-обёртки
  • SSR + кэширование, skeletons, error boundaries
  • SEO / OpenGraph для карточек модов
  • Collections / Modlists collections, collection_stars + экспорт ?format=prism|packwiz (Phase 2 хит)
  • Activity Feed - лента по подпискам (releases + collections + stars)
  • Org/Teams - /org/:login агрегатор, role=maintainer
  • Геймификация - badges (Early Adopter, Bug Hunter, Veteran) + Showcase SVG

Phase 3 - Поиск, качество данных и аналитика (см. docs/analytics.md, adr/005)

  • PostgreSQL FTS (to_tsvector + ts_rank) по name, summary, README
  • pg_trgm для неточных совпадений / опечаток
  • Опционально: pgvector для семантического поиска по описанию (эмбеддинги README)
  • Админ-панель / ручная модерация, флаг verified / suspicious
  • Indexium Analytics (bStats аналог):
    • Миграция 20260907000000_telemetry.sql (mod_telemetry_pings, mod_daily_stats, analytics_salts)
    • POST /api/v1/analytics/submit (gzip, валидация, daily_salt hash, Redis 1/15мин, без IP)
    • Крон агрегация COUNT(DISTINCT server_hash) → mod_daily_stats + TTL 30д
    • GET /mods/:slug/analytics?range=30d + GET /badges/:slug/servers.svg + sort=active_servers
    • Легковесный Java/Kotlin SDK dev.indexium:analytics (MIT, SimplePie, opt-out флаг)

Phase 4 - Надёжность и ограничения GitHub

  • GitHub App Install token - 5k-12.5k RPH вместо 60 RPH анонимных
  • Прямые редиректы на objects.githubusercontent.com - не проксировать трафик
  • Retry + exponential backoff, DLQ для воркера
  • Метрики: Prometheus / tracing + Grafana, алерты на lag очереди

Phase 5 - Деплой и эксплуатации

  • Dockerfile multi-stage для backend (distroless / alpine)
  • Dockerfile для frontend (adapter-node / adapter-static)
  • docker-compose.prod.yml / Fly.io / Railway / Hetzner
  • Бэкапы Postgres (PITR), миграции в CI
  • Документация деплоя (docs/deployment.md)

Phase 6 - Расширения (Backlog)

  • Поддержка CurseForge / Modrinth как доп. источников (опционально)
  • Webhooks для лаунчеров (подписка на обновления мода)
  • CLI для авторов (indexium publish)
  • Аналитика рантайма - аналог bStats (спроектирована, см. docs/analytics.md) → реализация в Phase 3
  • Аналитика скачиваний (агрегация без хранения персоналки)

Ближайшие 3 шага (Next Actions)

  1. docker-compose.yml + первая миграция SQL
  2. POST /webhooks/github с HMAC-проверкой и заглушкой очереди (in-memory channel)
  3. GET /mods - мок-данные из БД + подключение фронта

Как отмечать прогресс

  • При завершении задачи ставь [x] и добавляй ссылку на PR/коммит: [x] Задача (#12)
  • Если задача блочится - ставь [!] и опиши блокер в комментарии ниже.

Блокеры / Вопросы

  • Выбрать окончательно очередь: Redis Streams vs NATS JetStream vs pg-queue на старте?
    • Рекомендация: стартовать с Redis (уже нужен как кэш) → мигрировать на NATS если нужен strict ordering.
  • Где хостить Postgres на старте - Supabase / Neon / self-hosted?