AI Sana — Challenge Hub
Веб-платформа Challenge Hub с отдельными кабинетами бизнеса и студентов: конструктор задачи из свободного описания, рейтинг готовности 0–100, общий…
О проекте
Команда: DoubleMid
Кейс HackAlem.ai: Образование — AI Sana
Стадия: Рабочий MVP
Задача кейса: Challenge Hub: превратить задачу бизнеса в задание для студенческих команд
Суть
Веб-платформа Challenge Hub с отдельными кабинетами бизнеса и студентов: конструктор задачи из свободного описания, рейтинг готовности 0–100, общий каталог, отклики команд, выбор и подтверждение этапа с начислением баллов.
Как устроено
Бизнес вводит свободное описание, система задаёт минимум 3 уточняющих вопроса (OpenAI gpt-5.4-mini опционально, иначе контекстные резервные вопросы), ответы переносятся в редактируемую карточку без выдумывания фактов. Сервер детерминированно считает рейтинг полноты по 7 полям с весами (20/20/15/15/10/10/10), после ручного подтверждения карточка публикуется в каталог с сортировкой по рейтингу. Студенты шлют предложения, бизнес сравнивает их карточками/таблицей, выбирает команды, проверяет отчёт и подтверждает результат (+20 баллов). Данные хранятся в Cloudflare D1 через Drizzle, серверная авторизация с сессиями.
Ключевые решения
- детерминированный скоринг полноты карточки
- structured вопросы-уточнения с fallback
- серверные сессии и rate limit входа
- Drizzle-миграции
Особенности
Честно разделены AI-часть и детерминированная логика: рейтинг считает сервер только по подтверждённым полям, AI отключён по умолчанию и проверен на имитациях (17 тестов адаптера); test:built поднимает собранный Worker с временной D1 и прогоняет весь сценарий.
Стек
TypeScript · React · Next.js · Vite · Cloudflare Workers · Cloudflare D1 · Drizzle ORM · shadcn/ui
Модели
gpt-5.4-mini (OpenAI)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-0f8b3a7c-doublemid.
README
README.mdAI Sana — Challenge Hub
MVP команды DoubleMid: бизнес превращает потребность в понятную задачу, студенты выбирают её в общем каталоге, бизнес сравнивает предложения и подтверждает выполненный этап.
Быстрый запуск
Нужны Node.js 24 и npm. Команды выполняются в папке проекта:
git clone https://github.com/BAITC-Hacks/hack-0f8b3a7c-doublemid.git
cd hack-0f8b3a7c-doublemid
npm ci
npm run db:migrate
npm run dev
Откройте http://localhost:5173 (или адрес из вывода сервера). Миграции можно запускать повторно: применяются только новые. Данные сохраняются в .wrangler/state между перезапусками.
Для готовой сборки:
npm run build
npm start -- --port 4173
Откройте http://localhost:4173. Для чистого клона сначала нужны npm ci и npm run db:migrate. Локальная конфигурация базы — wrangler.local.jsonc: её имя намеренно отличается от автоматически загружаемой конфигурации сборщика, чтобы не дублировать DB.
Аккаунты
На странице входа есть две кнопки для быстрой демонстрации. Также можно войти по email и паролю:
| Кабинет | Демо-пароль | |
|---|---|---|
| Бизнес / администратор | [email protected] | AdminSana2026! |
| Студент, команда Qadam | [email скрыт] | StudentSana2026! |
| Дополнительные команды | [email скрыт] — [email скрыт] | StudentSana2026! |
Бизнес и студент могут работать из разных браузеров или устройств с одним сервером. Открывайте разные аккаунты в разных профилях/приватных окнах: обычные вкладки одного браузерного профиля разделяют cookie. Общие данные обновляются каждые 15 секунд и при возвращении в окно.
Публичные пароли предназначены для учебного показа. Перед закрытым пилотом задайте в серверном окружении DEMO_LOGIN_ENABLED=false, ADMIN_PASSWORD, STUDENT_PASSWORD и, если нужны, TEAM2_PASSWORD–TEAM5_PASSWORD. Без заданного пароля соответствующий аккаунт при выключенном демо недоступен. Самостоятельной регистрации и восстановления паролей пока нет.
Что доработано
- Вместо переключателя ролей — серверный вход, отдельные кабинеты и отзыв сессии при выходе.
- Общая база задач для всех аккаунтов; черновики видит только бизнес. Студент получает только свои предложения, но видит общее число откликов и рейтинг достижений.
- Обзор бизнеса: публикации, черновики, новые отклики, результаты на проверке. Обзор студента: интересные задачи, предложения, работа и баллы.
- Конструктор: свободное описание → минимум 3 уточнения → редактируемая карточка → ручное подтверждение → публикация.
- Рейтинг 0–100, расшифровка, недостающие поля и пересчёт. Каталог сортируется по рейтингу; есть поиск и фильтры темы/готовности.
- Неограниченное число откликов: идея, план, срок и HTTP(S)-ссылка. Команда определяется сессией, а не присланным идентификатором.
- Бизнес сравнивает предложения карточками или таблицей; выбирает одну, несколько или ни одной команды.
- Выбранная команда отправляет отчёт. Только после этого бизнес проверяет и подтверждает результат. +20 баллов один раз за отклик; сам выбор баллов не даёт.
- Адаптивный экран входа, два обзора, рекомендации по интересам и рейтинг команд за подтверждённые результаты.
Рейтинг
| Показатель | Вес |
|---|---|
| Контекст и потребность | 20 |
| Данные и материалы | 20 |
| Ожидаемый результат | 15 |
| Критерии успеха | 15 |
| Ограничения | 10 |
| Пользователи | 10 |
| Контакт и взаимодействие | 10 |
Контекст/потребность разделены на 10+10, контакт/взаимодействие — на 5+5. Сервер начисляет баллы только за заполненные и подтверждённые поля. От 8 символов, распространённые заглушки не учитываются. Это оценка полноты, не семантическая экспертиза. Предварительный балл в редакторе не является начисленным рейтингом.
0–39 — требует уточнения; 40–69 — рабочая; 70–89 — готовая; 90–100 — приоритетная. Последнее название сохранено из исходного проекта: присланный текст задания обрывается на диапазоне 70–89. Опубликованная карточка доступна для откликов при любом балле. Неподтверждённые личные черновики в общий каталог не попадают.
Помощник
Без ключей и платных запросов работают контекстные резервные вопросы. Ответы пользователя переносятся в карточку, отсутствующие факты не выдумываются. Для OpenAI скопируйте .env.example в .env.local, задайте OPENAI_API_KEY и включите OPENAI_REQUESTS_ENABLED=true только если готовы оплачивать запросы. Модель задаётся OPENAI_MODEL; существующая настройка — gpt-5.4-mini.
Реальное обращение к OpenAI в этой доработке не выполнялось. Контракт и резервные режимы проверены на имитациях. При недоступности модели конструктор продолжает работать. Контактное поле исключено из AI-запроса; личные сведения в свободном тексте автоматически не удаляются. Подробности — docs/OPENAI-INTEGRATION.md.
Автоматические проверки без платных запросов
После установки зависимостей:
npm run typecheck
npm run lint
npm test
npm run build
npm run test:built
test:built запускает собранный Worker с временной D1, применяет обе миграции и проверяет вход, права, общий каталог, скрытые черновики, предложение от своего аккаунта, ручной выбор нескольких команд, отчёт, подтверждение, однократные баллы, конфликт правок, повторы запросов, недопустимые ссылки и выход. Это рекомендуемая безопасная проверка: база пользователя не меняется.
node scripts/test-api.mjs предназначен только для отдельного тестового сервера с исходными демо-данными, потому что создаёт и изменяет записи в общем каталоге. Не запускайте его на рабочем показе. TEST_URL задаёт адрес сервера.
Состав
app/page.tsx,components/hub/— интерфейс и кабинеты.app/api/auth/route.ts,lib/auth.ts— вход, ограничения попыток, сессии.app/api/workspace/route.ts— серверная авторизация действий и бизнес-логика.lib/domain.ts— рейтинг, типы, вопросы и синтетические примеры.db/,drizzle/— D1 и миграции.docs/CRITERIA.md— соответствие присланному кейсу.docs/CLICK-THROUGH.md— сценарий для демонстрации.docs/REVIEW-AND-TESTING.md— проверенные изменения и ограничения.
Архив содержит исходники, миграции и lockfile; не содержит зависимостей, локальной базы и секретов. Изменения не отправлялись в GitHub: доступа к приватному репозиторию в сессии нет. Замените соответствующие файлы в своей рабочей копии, проверьте запуск и сохраните обычным коммитом. Старые записи исходной версии остаются в базе под прежними идентификаторами пространств; новый общий каталог создаётся отдельно и не удаляет их. npx tsc --noEmit node scripts/test-domain.mjs node --test scripts/test-openai.mjs scripts/test-reliability.mjs npm run build node scripts/test-built.mjs
`test-built.mjs` запускает готовую сборку на свободном локальном порте, создаёт временную базу, проверяет страницу и клиентские файлы, затем выполняет серверный сценарий. Ключ не загружается, реальные AI-запросы выключены, база пользователя не используется.
Дополнительные команды:
```sh
# API-проверка уже работающего сервера; по умолчанию http://localhost:4173
node scripts/test-api.mjs
# Проверка отсутствия локального ключа в исходниках и сборке
# Требует .env.local с ключом, существующую dist и Git в PATH
node scripts/check-secret-boundary.mjs
Для другого адреса API-теста задайте TEST_URL. Например, в PowerShell:
$env:TEST_URL = 'http://localhost:5173'
node scripts/test-api.mjs
API-тест создаёт отдельное пространство. Он требует выключенных реальных AI-запросов и проверяет публикацию при низком рейтинге, отклик, выбор, подтверждение, сохранение, изоляцию, неверные запросы, повторную отправку и конкурентные изменения.
Зафиксированные проверки текущей версии: 17 тестов OpenAI-адаптера на имитациях ответов и 9 тестов восстановления форм/чтения запросов прошли; доменные проверки, TypeScript, сборка и серверный сценарий также прошли. Интерфейс проверялся на компьютере и экранах шириной 390 и 320 px. Это проверка конкретных сценариев, а не гарантия отсутствия любых ошибок. Подробности — отчёт об аудите.
Для отдельной проверки модели предусмотрен scripts/test-live-ai.mjs. Он делает один реальный запрос только с флагом --allow-paid-request; запускать его следует после согласования расходов. Этот тест не входит в команды выше и ещё не выполнялся.
8. Данные и интеграции
- Демонстрационные данные: массивы
seedDrafts,seedTasks,teams,seedProposalsвlib/domain.ts. Названия организаций, контакты, задачи и предложения синтетические. Упоминания CSV/PDF внутри карточек описывают учебные условия; импорта этих файлов и подключённых наборов данных нет. - Данные пользователя: текст карточек, отклики, решения и описания подтверждённых этапов сохраняются в D1. Незавершённые формы дополнительно сохраняются в
sessionStorageтекущей вкладки. - OpenAI: внешний API используется только после явного включения. Модель по умолчанию —
gpt-5.4-mini. Доступ ключа, баланс и качество реального ответа в этом проекте пока не подтверждены. - Cloudflare D1 / Workers: база и среда выполнения; локально эмулируются установленными инструментами.
- Sites: в репозитории есть конфигурация привязки D1 и инфраструктура сборки. Публичное размещение не подтверждено.
- Ссылки на прототипы: принимаются HTTP(S)-адреса без логина и пароля. Приложение хранит ссылку, но не проверяет работоспособность или качество внешнего прототипа.
Автоматического импорта задач из внешних систем, отправки писем, подключения к университетским базам или NVIDIA-сервисам нет.
9. Ограничения текущей версии
- Демонстрационные роли вместо отдельных аккаунтов. Нет регистрации организаций/команд и серверных прав на отдельные роли. Другой браузер получает другое пространство. Публичный многопользовательский каталог ещё не реализован.
- Рейтинг оценивает полноту текста. Он не проверяет достоверность, смысл, измеримость критериев или реализуемость задачи. Длинный бессодержательный ответ может получить баллы.
- Живой AI не проверен. OpenAI-адаптер протестирован на имитациях; по умолчанию работают вопросы по правилам. Одна только настроенная переменная ключа не подтверждает доступность модели.
- Карточку формирует пользователь. Автоматического переписывания всего задания моделью, семантического matching и автоматического назначения команд нет.
- Лимиты AI действуют в одном экземпляре сервера. Между реальными запросами пространства предусмотрена пауза 30 секунд. Это не постоянная квота и не финансовый лимит; для открытого пилота нужны авторизация и надёжный контроль расходов.
- Восстановление формы ограничено вкладкой. Для постоянного хранения задачи нужно сохранить черновик; отклик сохраняется на сервере после отправки. Очистка cookie создаёт новое пространство и не является механизмом восстановления доступа к прежним записям.
- Подтверждение этапа ручное. Нет автоматической проверки доказательств, загрузки файлов или системы нескольких этапов на один отклик.
- Публичный деплой не подтверждён. Для реального пилота также потребуются настройка секретов, резервного копирования, мониторинга и прав доступа. Vinext используется в beta-версии.
10. Развёрнутая версия
Подтверждённой публичной ссылки в текущем репозитории нет. Для оценки используйте локальный запуск по разделу 6.
Адрес localhost доступен только на компьютере с запущенным сервером и не является ссылкой на deployed-версию. GitHub содержит исходный код и документацию, но сам по себе не запускает это приложение с сервером и базой.
| Аккаунт | Демо-пароль | |
|---|---|---|
| Админ | [email protected] | AdminSana2026! |
| Студент | [email скрыт] | StudentSana2026! |
11. Материалы для защиты
Авторы коммитов
История коммитов
- 2026-09-23 17:53Merge pull request #1 from BAITC-Hacks/feat/ai-sana-accounts-20260923-174230aldiyarb123
- 2026-09-23 17:51Merge branch 'main' into feat/ai-sana-accounts-20260923-174230aldiyarb123
- 2026-09-23 17:42feat: add admin and student accounts, shared workflow and demo credentialsAldiyar
- 2026-09-23 17:42Update README.mdaldiyarb123
- 2026-09-23 17:18docs: prepare Russian README for hackathon judgesdevor11
- 2026-09-23 17:01feat: refine business UI and harden AI Sana workflowsdevor11
- 2026-09-23 14:10feat: add AI Sana Challenge Hub MVP and hackathon demo docsdevor11
Структура репозитория (140 файлов)
.env.example .gitignore .npmrc .openai/hosting.json README.md app/api/auth/route.ts app/api/workspace/route.ts app/chatgpt-auth.ts app/globals.css app/layout.tsx app/page.tsx cloudflare-env.d.ts components.json components/hub/dashboard.tsx components/hub/login.tsx components/hub/workspace-ui.tsx components/ui/accordion.tsx components/ui/alert-dialog.tsx components/ui/alert.tsx components/ui/aspect-ratio.tsx components/ui/attachment.tsx components/ui/avatar.tsx components/ui/badge.tsx components/ui/breadcrumb.tsx components/ui/bubble.tsx components/ui/button-group.tsx components/ui/button.tsx components/ui/calendar.tsx components/ui/card.tsx components/ui/carousel.tsx components/ui/chart.tsx components/ui/checkbox.tsx components/ui/collapsible.tsx components/ui/combobox.tsx components/ui/command.tsx components/ui/context-menu.tsx components/ui/dialog.tsx components/ui/direction.tsx components/ui/drawer.tsx components/ui/dropdown-menu.tsx components/ui/empty.tsx components/ui/field.tsx components/ui/form.tsx components/ui/hover-card.tsx components/ui/input-group.tsx components/ui/input-otp.tsx components/ui/input.tsx components/ui/item.tsx components/ui/kbd.tsx components/ui/label.tsx components/ui/marker.tsx components/ui/menubar.tsx components/ui/message-scroller.tsx components/ui/message.tsx components/ui/native-select.tsx components/ui/navigation-menu.tsx components/ui/pagination.tsx components/ui/popover.tsx components/ui/progress.tsx components/ui/radio-group.tsx components/ui/resizable.tsx components/ui/scroll-area.tsx components/ui/select.tsx components/ui/separator.tsx components/ui/sheet.tsx components/ui/sidebar.tsx components/ui/skeleton.tsx components/ui/slider.tsx components/ui/sonner.tsx components/ui/spinner.tsx components/ui/switch.tsx components/ui/table.tsx components/ui/tabs.tsx components/ui/textarea.tsx components/ui/toggle-group.tsx components/ui/toggle.tsx components/ui/tooltip.tsx db/index.ts db/schema.ts db/store.ts docs/ARCHITECTURE.md docs/CLICK-THROUGH.md docs/CRITERIA.md docs/DEMO-AND-PITCH.md docs/OPENAI-INTEGRATION.md docs/REVIEW-AND-TESTING.md docs/screenshots/business.png docs/screenshots/comparison.png docs/screenshots/login.png docs/screenshots/mobile.png docs/screenshots/student.png drizzle.config.ts drizzle/0000_keen_iron_lad.sql drizzle/0001_accounts.sql drizzle/meta/0000_snapshot.json drizzle/meta/0001_snapshot.json drizzle/meta/_journal.json eslint.config.mjs examples/d1/app/api/notes/route.ts examples/d1/db/schema.ts hooks/use-mobile.ts lib/ai-config.ts lib/ai-types.ts lib/auth-types.ts lib/auth.ts lib/domain.ts lib/editor-cache.ts lib/format.ts lib/openai-questions.ts lib/request-body.ts lib/utils.ts next.config.ts package-lock.json package.json postcss.config.mjs public/favicon.svg public/file.svg public/globe.svg public/window.svg scripts/build-verified.sh scripts/check-secret-boundary.mjs scripts/execution-profile.mjs scripts/install-ci.mjs scripts/install-ci.sh scripts/install-pnpm.sh scripts/npm-install.mjs scripts/pnpm-install.mjs scripts/run-framework.mjs scripts/sites-env.mjs scripts/sites-env.sh scripts/test-api.mjs scripts/test-built.mjs scripts/test-domain.mjs scripts/test-live-ai.mjs scripts/test-openai.mjs scripts/test-reliability.mjs scripts/windows-compat.cjs tsconfig.json vite.config.ts wrangler.local.jsonc
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.