AAYMA
RU
Войти

AI Sana — Challenge Hub

Веб-платформа Challenge Hub с отдельными кабинетами бизнеса и студентов: конструктор задачи из свободного описания, рейтинг готовности 0–100, общий…

Рабочий MVP
Команда «DoubleMid» 8💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: 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.md

AI 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Демо-пароль
Бизнес / администратор[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. Ограничения текущей версии

  1. Демонстрационные роли вместо отдельных аккаунтов. Нет регистрации организаций/команд и серверных прав на отдельные роли. Другой браузер получает другое пространство. Публичный многопользовательский каталог ещё не реализован.
  2. Рейтинг оценивает полноту текста. Он не проверяет достоверность, смысл, измеримость критериев или реализуемость задачи. Длинный бессодержательный ответ может получить баллы.
  3. Живой AI не проверен. OpenAI-адаптер протестирован на имитациях; по умолчанию работают вопросы по правилам. Одна только настроенная переменная ключа не подтверждает доступность модели.
  4. Карточку формирует пользователь. Автоматического переписывания всего задания моделью, семантического matching и автоматического назначения команд нет.
  5. Лимиты AI действуют в одном экземпляре сервера. Между реальными запросами пространства предусмотрена пауза 30 секунд. Это не постоянная квота и не финансовый лимит; для открытого пилота нужны авторизация и надёжный контроль расходов.
  6. Восстановление формы ограничено вкладкой. Для постоянного хранения задачи нужно сохранить черновик; отклик сохраняется на сервере после отправки. Очистка cookie создаёт новое пространство и не является механизмом восстановления доступа к прежним записям.
  7. Подтверждение этапа ручное. Нет автоматической проверки доказательств, загрузки файлов или системы нескольких этапов на один отклик.
  8. Публичный деплой не подтверждён. Для реального пилота также потребуются настройка секретов, резервного копирования, мониторинга и прав доступа. Vinext используется в beta-версии.

10. Развёрнутая версия

Подтверждённой публичной ссылки в текущем репозитории нет. Для оценки используйте локальный запуск по разделу 6.

Адрес localhost доступен только на компьютере с запущенным сервером и не является ссылкой на deployed-версию. GitHub содержит исходный код и документацию, но сам по себе не запускает это приложение с сервером и базой.

АккаунтEmailДемо-пароль
Админ[email protected]AdminSana2026!
Студент[email скрыт]StudentSana2026!

11. Материалы для защиты

Звёзды
⭐ 0
Форки
0
Язык
TypeScript
Последний push
в прошлом месяце
Коммиты
7
Авторы
3
Файлы
140
Ветки
2

Авторы коммитов

aldiyarb123 3devor11 3Aldiyar 1

История коммитов

  • 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
Ветки (2)

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.