Проверить:
- регистрация / вход
- покупка токенов
- списание токенов
- возврат токенов при ошибке
- генерации через каждый AI-инструмент
- загрузка файлов
- история задач
- ошибки API
- лимиты
- работа очередей
- админка
Полная дорожная карта AI Creative Hub: Стадия 1 — 10 этапов MVP-сборки, Стадия 2 — 13 этапов превращения в SaaS.
Канон — ai-hub/ROADMAP.md в репо.
ai-hub/docs/architecture-research.md
0000_init.sql + 0001_wallet_functions.sql + 0002_onboarding_bonus.sqlusers (Auth.js — id, email, name, role)token_wallets (available + reserved + total_purchased + total_spent)token_transactions (append-only ledger для аудита)ai_tools (каталог инструментов)ai_jobs (история запусков с idempotency_key)media_assets (S3-ключи MinIO + метаданные)payments + payment_packages + promo_codes + promo_redemptionsaccounts + sessions + verification_tokenswallet_reserve · wallet_charge · wallet_refund · wallet_crediton_user_created — auto-create wallet + welcome bonus 100 токеновupdated_at на token_wallets / ai_tools / ai_jobssrc/lib/db/schema.ts — single source of truthUser, AiTool, AiJob, Payment, NewAiJob, ...)JobStatus, ProviderId, ToolCategory, ...)Database interface — аналог Supabase Databasedrizzle/seed/tools.sql (image, video, face, content)/dashboard (server component, protected middleware'ом)/wallet (4 metric cards)/history (50 свежих jobs с status-бэйджами, error_message)/tools (13 моделей по 6 категориям: image, video, face, audio, content, analysis)/gallery — grid всех генераций пользователя с presigned URLs из MinIO/tools/[slug] с дженерик-runner'ом — форма рендерится из input_schema JSON-схемыwallet_reserve() бросает INSUFFICIENT_FUNDS (P0001) если available < cost→ 402UPDATE token_wallets SET available -= N, reserved += N WHERE available >= N RETURNINGrace-freewallet_charge() в webhook handler'е + worker'е. Partial charge поддержан (refund разницы)wallet_refund() в catch блоке worker'а + watchdog подбирает stuck jobs >15minusers (триггер on_user_created)token_transactions — все 7 типов (purchase, spend, refund, bonus, reserve, release, adjustment) с balance_after для аудитаjob.status уже finalized)src/lib/providers/router.ts, статический map ProviderId → ProviderAdapterProviderAdapter (src/lib/providers/types.ts):submit(args) — async-вариант runJob(input). Принимает model + input + webhookUrl + jobId, возвращает {status, providerJobId}getStatus(providerJobId) — polling-fallback, идентичен спецификации getJobStatus(jobId)parseWebhook(headers, body, secret) — async-вариант getResult(jobId). Верифицирует подпись, возвращает завершённый результатcancel(providerJobId) — optional, поддержан где провайдер позволяетFAL_WEBHOOK_SECRET · REPLICATE_WEBHOOK_SECRET и т.д. (src/lib/providers/secrets.ts)fal-ai/flux/dev · 5 токеновnightmareai/real-esrgan · 3 токенаfal-ai/birefnet/v2 · 2 токенаcdingram/face-swap · 10 токеновfal-ai/flux-pro/kontext · 8 токеновingestJobMedia() обходит JSON output, скачивает медиа-URLs, кладёт в bucket, инсертит media_assets rowfal-ai/kling-video/v1.6/standard/image-to-video · 80 токеновfal-ai/kling-video/v1.6/standard/text-to-video · 100 токеновfal-ai/topaz/upscale/videobuyPackage(slug) создаёт Stripe Checkout session (price_data, без manual Stripe products)/api/webhooks/stripe, верифицирует подпись через stripe.webhooks.constructEventcheckout.session.completed зовём wallet_credit(type='purchase')/wallet (token_transactions) + /admin/payments (registry)tma.46-62-215-11.nip.io)/api/tools/[slug]/run с подсказкой «нужно N токенов»wallet_refund + status='refunded' + error_codestatus='refunded' с error от провайдераwallet_refund() атомарно возвращает reserved → available + пишет ledger rowMAX_CONCURRENT_JOBS_PER_USER) → 429 с понятной ошибкой/api/health — ping DB + Redis, JSON с таймингами, 200/503. Используется в Docker HEALTHCHECKchild(scope), LOG_LEVEL env/admin/users — таблица 100 свежих с wallet'ом и jobs count, inline grant ±N tokens/admin/jobs — фильтры по статусу, manual refund button с confirm/admin/payments (платежи) + per-user в /wallet (token_transactions)/admin/tools · inline tokenCost-edit, изменения мгновенно/admin/toolsrequireAdminPage() / requireAdminApi()role='admin'/api/admin/jobs/:id/refund · /api/admin/tools/:id · /api/admin/users/:id/grant-tokenstoken_transactions.metadata с by: admin@emailprovider_cost_usd vs charged_tokens) — backlogoutput: "standalone" для слим runtime image (~200MB)aisales_aisales-net)ai_hub создана в aisales-postgres на проде, 13 таблиц + триггерыai-hub-media созданpg_backup.sh.bak.20260519_093701, backup.env.bak.…pg_backup.sh патч под PG_DBS список — PATCH в DEPLOY.md, юзер применяет вручную (auto-classifier заблокировал авто-правку критичного backup-скрипта)aihub-app.46-62-215-11.nip.io → готовый блок в DEPLOY.mdFAL_KEY, REPLICATE_API_TOKEN, STRIPE_SECRET_KEY, SMTP_URLtma.46-62-215-11.nip.io)aux_backup.sh через mc mirror или bucket replicationПроверить:
Для каждого AI-инструмента посчитать:
$0.35 → продаём за $1.2–1.5 в токенах → маржа 60–75%
Иначе люди зайдут, увидят много кнопок и выйдут.
Не просто «text-to-image», а:
Стили:
→ результат получается предсказуемее.
Пользователь загружает:
→ все генерации адаптируются под его бренд.
Позиционирование: Единый AI-кабинет для создания Reels, рекламы, видео, фото и креативов без 20 разных подписок.
Главные блоки:
Должен:
Вот это станет твоим отличием от обычного агрегатора.
После этого будет понятно, что масштабировать.
.env — никогда в коде, никогда не отдаются на frontend/api/tools/[slug]/run → BullMQ → worker)ai-hub-media, presigned URLsai-hub/ изолирован от pages/, infra-worker/, других сервисов в монорепо/ai-hub — свой Postgres-проект ai_hub, свой compose, свой поддомен
Глубокое research-исследование (~700 строк) загружено в проект как ai-hub/docs/architecture-research.md.
Охватывает провайдерскую стратегию, ledger-first wallet, pricing engine, fallback chains, security/GDPR, 6-month budget и подробный mapping research → текущая реализация.
quote() API для динамической оценки цены до резерваjob_attempts для retry/fallback lineageprovider_cost_usd, нет агрегаций по марже