| .github/workflows | ||
| backend | ||
| docs | ||
| frontend | ||
| memory | ||
| ops | ||
| .editorconfig | ||
| .env.example | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| Caddyfile | ||
| docker-compose.prod.yml | ||
| docker-compose.yml | ||
| Makefile | ||
| README.md | ||
| sshkey.txt | ||
Generative Design + Site Finder
Две продуктовые линии в одной воронке: Site Finder (AI-подбор инвестиционных земельных участков) + Generative Design (автоматическая генерация концепций застройки) для девелоперов РФ.
North Star
К концу месяца 3: 3 платящих пилота (≥30 тыс. ₽/мес каждый) + заявка в реестр российского ПО → право на Раунд А (20–25 млн ₽).
Acceptance criteria разбиты на 3 блока (функционально / бизнесово / технически). Правило перехода: 3/3 → Раунд А; 2/3 → продление Фазы 0 на 1–2 мес.; 1/3 или меньше → стоп проекта.
Текущий статус (26 апреля 2026)
Инфраструктура: live на HTTPS. Прод доступен по https://gendsgn.ru/, Let's Encrypt cert получен. Полный цикл автодеплоя из GitHub Actions работает. 26.04 прод полностью пересоздан (down -v + redeploy) — БД свежая, backend в multi-stage образе под non-root пользователем, healthcheck-и работают, ловит ошибки в Sentry.
| Что | Где | Статус |
|---|---|---|
| Production URL | https://gendsgn.ru/ | ✅ HTTP/2 + HTTP/3, валидный TLS |
| Health endpoint | https://gendsgn.ru/health | ✅ {"status":"ok","environment":"prod"} |
| www → apex | https://www.gendsgn.ru/ | ✅ 301 redirect |
| Production VPS | Beget Cloud, Москва, 2 vCPU / 4 GB / 40 GB NVMe | ✅ работает |
| IP сервера | 46.173.16.127 |
— |
| Домен | gendsgn.ru (Beget, до 26.04.2027, ЕСИА VERIFIED) |
✅ DNS на 8.8.8.8/1.1.1.1 |
| Postgres + PostGIS 3.4 | Docker, в составе compose | ✅ Up (healthy) |
| Redis 7 | Docker | ✅ Up (healthy, redis-cli ping) |
| Backend FastAPI | Docker, multi-stage, non-root, 1.44 GB | ✅ Up (healthy, curl /health) |
| Frontend Next.js 15 | Docker, multi-stage, npm ci | ✅ Up |
| Caddy reverse proxy | Docker, ports 80/443 | ✅ Up + auto-TLS Let's Encrypt |
| GitHub Actions deploy | .github/workflows/deploy.yml |
✅ build → push GHCR → ssh deploy → git pull → caddy reload |
| GHCR пакеты | ghcr.io/lekss361/gendesign-{backend,frontend} |
приватные, сервер авторизуется через PAT |
| UFW firewall | 22 / 80 / 443 | ✅ активен |
| SSH hardening | root login off, password auth off | ✅ |
| Sentry | проект gendesign-backend (org qqq, free tier) |
✅ DSN на VM, события приходят |
| GitHub Issues / Milestones | 12 issues, 3 milestones (Stage 1 / Stage 2 / Infra Hardening) | ✅ backlog засеян |
| Бэкапы pg_dump | ops/backup.sh готов |
⏸ S3-бакет не настроен (Selectel/Yandex) |
Решение по плану разработки: pending. Антон (второй разработчик) сообщил о доступе к ДДУ-данным. Решается в понедельник 27.04.2026 — выбор между:
- Plan A (Analytics First) — Stage 1 переезжает на «3 плитки» аналитики (что строить / по какой цене / за какое время), Generative и Site Finder сдвигаются;
- Original plan — Stage 1 = Generative MVP, Stage 2 = Site Finder, аналитика как enrichment.
Зависит от 5 факторов канала ДДУ: легальность, поля, покрытие, свежесть, условия коммерческого использования. См. сущности PlanA_AnalyticsFirst_Apr25 и SalesTracking_Strategy_Apr25 в графе памяти.
Структура репозитория
gendesign/
├── backend/ # Python 3.12 / FastAPI / PostGIS
│ ├── pyproject.toml # uv-проект, ruff/mypy/pytest конфиги
│ ├── Dockerfile # с системными deps под Geo + WeasyPrint
│ ├── .env.example
│ ├── app/
│ │ ├── main.py # FastAPI + Sentry + /health
│ │ ├── core/ # config (Pydantic Settings), db (SQLAlchemy)
│ │ ├── api/v1/ # concepts.py, parcels.py
│ │ ├── schemas/ # Pydantic-контракты для openapi-typescript
│ │ ├── services/
│ │ │ ├── generative/ # Stage 1: geometry, teap, financial
│ │ │ ├── site_finder/ # Stage 2: parser, scorer, filters
│ │ │ └── exporters/ # Stage 1c: pdf, excel, dxf
│ │ ├── models/parcel.py # GeoAlchemy2 + PostGIS
│ │ └── workers/celery_app.py # Stage 2a: daily PKK sync
│ └── tests/
├── frontend/ # Next.js 15 / React 19 / TypeScript / Leaflet
│ ├── package.json # включая `npm run codegen` → openapi-typescript
│ ├── Dockerfile # multi-stage, output: standalone
│ ├── public/ # static assets (gitkeep пока пусто)
│ └── src/app/
│ ├── page.tsx # / — главная
│ ├── concept/page.tsx # /concept — Generative Design
│ └── site-finder/page.tsx # /site-finder — Site Finder
├── memory/
│ └── memory-gendesign.jsonl # хард-линк на C:\mcp\.aim — общий граф памяти
├── docs/ # стратегические документы (бизнес-план, цели MVP)
├── ops/ # эксплуатация
│ ├── backup.sh # pg_dump cron + опциональный S3 upload
│ └── restore.sh # восстановление из дампа (RESTORE_CONFIRM=yes)
├── backend/
│ ├── alembic.ini, alembic/ # миграции БД (versions/ пуст до Stage 2a)
│ └── db/init/ # init-скрипты, монтятся в /docker-entrypoint-initdb.d
│ └── 99_drop_unused_extensions.sql # дроп TIGER/topology/fuzzystrmatch на свежем volume
├── .env.example # шаблон prod env (POSTGRES_*, IMAGE_TAG)
├── docker-compose.yml # dev: Postgres + Redis + backend + frontend
├── docker-compose.prod.yml # prod: образы из GHCR + Caddy + Postgres+Redis
├── Caddyfile # авто-TLS Let's Encrypt для gendsgn.ru
├── Makefile # make up / migrate / migration / test / codegen / pre-commit-install
├── .pre-commit-config.yaml # ruff + prettier + housekeeping hooks
└── .github/workflows/
├── ci.yml # ruff + mypy(core) + pytest + frontend build
└── deploy.yml # build → push в GHCR → ssh: git fetch + reset --hard + caddy reload
Технический стек (v2.2)
Backend: Python 3.12, FastAPI, SQLAlchemy 2.0, GeoAlchemy2, Pydantic v2, Alembic, Celery + Redis, httpx Geo: Shapely 2.0, GeoPandas, Pyproj (WGS84 ↔ МСК-66 для Свердловской обл.) ML: scikit-learn (XGBoost — отложен на Фазу 1, в Discovery эвристики) БД: PostgreSQL 16 + PostGIS 3.4, Redis 7 Frontend: Next.js 15, React 19, TypeScript 5, Tailwind 4, TanStack Query, Leaflet (Mapbox в Stage 2b), react-leaflet 5 Экспорт: WeasyPrint (PDF), ezdxf (DXF), openpyxl (Excel) Dev: uv (lockfile зафиксирован), ruff (lint+format), mypy (strict только на core), pytest, pre-commit (hooks: ruff, prettier, detect-private-key)
Команда и порядок работы
2 фуллстек-разработчика, оба part-time 20 ч/нед — итого ~40 person-hours/нед, эффективных с координацией ~33.
Ритм:
- 1 синк/нед (30 мин, понедельник)
- daily-async в Telegram
- PR review обязательный
- Trunk-based: feature ветки ≤ 3 дней
- Codegen TS-типов из Pydantic (
npm run codegen) — без этого 2 фуллстека плодят расхождения в API-контракте
Этапы MVP (12 недель, базовый план)
Stage 0 — Скелет (нед. 1) ✅ выполнено
Монорепо backend+frontend, Docker с PostGIS+Redis, FastAPI hello, Next.js hello, openapi-typescript codegen, GitHub Actions CI, ruff + mypy(core) + pytest. Без JWT (single-tenant + X-Demo-User до Раунда А). Production VPS поднят, GHCR-деплой работает.
Stage 1 — Generative MVP (нед. 2–7) ⏸ pending решения по Plan A
- 1a (нед. 2–3): геометрия + API-контракт. Shapely-сервис (отступы, сетка), Pydantic-схемы,
POST /api/v1/conceptsс заглушкой. Фронт: страница/concept, Leaflet, импорт GeoJSON, форма параметров, 3 варианта в табах. - 1b (нед. 4–5): алгоритм размещения. Жадное заполнение, 3 стратегии (max площадь / max инсоляция / balanced), STRtree для коллизий. Цель ≤10 сек, fallback 15 сек.
- 1c (нед. 6–7): ТЭП + финмодель + экспорты. WeasyPrint PDF, ezdxf, openpyxl. UI кнопок скачивания.
Acceptance Stage 1 (конец нед. 7): полигон → 3 варианта → ТЭП + финмодель → PDF/Excel/DXF.
Stage 2 — Site Finder MVP (нед. 8–12)
- 2a (нед. 8–9): data pipeline. Парсер ПКК Rosreestr (httpx async, retries), модель
Parcelс GeoAlchemy2, ≥1000 участков Екатеринбурга. Overpass API для POI, ДОМ.РФ/ЦИАН для цен м², кеш в Redis. Опционально: воркерsales_tracker.py— ежесуточный мониторинг шахматок застройщиков (Velocity Score). - 2b (нед. 10–11): скоринг + API + UI. 3 критерия (расстояние до центра, плотность POI в 1 км, цена района),
POST /api/v1/parcels/search. Карта с градацией по рейтингу, фильтры, карточка. - 2c (нед. 12): интеграция + полировка. Кнопка «Обсчитать концепцию», демо-наполнение 50 участков, бэкапы БД, подача в реестр ПО.
Альтернативный план A (Analytics First)
Если Антон в понедельник подтвердит легальный канал ДДУ-данных — Stage 1 переезжает на «3 плитки» аналитики (что строить / по какой цене / за какое время), Generative переходит на Stage 2 со Smart Defaults на основе аналитики, Site Finder — на Stage 3 с Velocity Score из ДДУ. См. PlanA_AnalyticsFirst_Apr25 в графе.
Что урезано из v2.2 из-за part-time × 2
- XGBoost-скоринг → Фаза 1 (с реальными данными от пилотов)
- JWT-auth с refresh → перед Раундом А
- mypy --strict — только на core (
generative/*,site_finder/scorer.py) - Время генерации ≤ 15 сек как fallback (а не 10 сек)
Quick start (локально)
Требования: Docker Desktop, Node.js 20+, uv (для backend dev вне Docker).
# 1. Скопировать env-файлы
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env
cp .env.example .env # опционально, для prod compose
# 2. Запустить всё
docker compose up -d --build
# или: make up
# 3. Проверить
curl http://localhost:8000/health
# → {"status":"ok","environment":"dev"}
# Frontend → http://localhost:3000
# Swagger docs → http://localhost:8000/docs
Полезное:
make logs # tail логов всех сервисов
make backend-shell # bash внутри backend контейнера
make migrate # alembic upgrade head (когда добавим миграции)
make test # pytest
make lint # ruff check
make typecheck # mypy на core
make codegen # обновить TS-типы из OpenAPI
Production хостинг — Beget VPS
Текущая live-конфигурация: Beget Cloud, Москва, Standard 3+ GHz, 2 vCPU / 4 GB / 40 GB NVMe.
Стоимость: ~33 ₽/день сервер + ~5 ₽/день IPv4 = ~1140 ₽/мес. Плюс домен .ru (~17 ₽/мес).
Что крутится на VM (/opt/gendesign):
- 5 контейнеров через
docker-compose.prod.yml: postgres, redis, backend, frontend, caddy - Backend и frontend образы пуллятся из приватного GHCR
- Persistent volumes:
gendesign_postgres_data,gendesign_redis_data,gendesign_caddy_* - Backend и frontend биндятся на
127.0.0.1:8000и127.0.0.1:3000— наружу выходит только Caddy на:80/:443
Доступ: SSH-only по ключу к non-root пользователю gendesign. Root login отключён, password auth отключён, fail2ban Beget активен.
Триггеры миграции на Yandex Cloud
Переезжаем на YC Managed PostgreSQL + Compute + Container Registry, когда:
- Подписан 3-й платящий пилот (~ конец мес. 3)
- Закрылся Раунд А
- Идёт переговор с госзаказчиком (нужен реестр ПО + солидная инфра)
- БД > 10 GB или появилось > 50 RPS
Стоимость production на YC: ~10–15 тыс ₽/мес.
Что осталось до «infra-ready»
Купить домен—gendsgn.ruзарегистрирован в Beget 26.04.2026 (199₽/420₽). DNS на NS Beget, A-записи прописаныЕСИА-верификация админа домена— пройдено 26.04, статусREGISTERED, DELEGATED, VERIFIEDCaddy TLS на— Let's Encrypt cert получен, HTTPS живётgendsgn.ruSentry DSN— проектgendesign-backendсоздан в orgqqq, DSN в/opt/gendesign/backend/.env, тестовое событие прошлоGitHub Issues / Milestones / Labels— backlog засеян (см. Issues)- Настроить ежесуточный
pg_dump→ Object Storage. Скриптops/backup.shготов, осталось создать Selectel/Yandex bucket и положить креды в/etc/default/gendesign-backupна VM (#3) - Прокинуть
SENTRY_RELEASEв deploy.yml для tracking релизов в Sentry (#4) - Подключить Антона к knowledge-graph (#11)
- При следующем wipe
down -v— TIGER/topology/fuzzystrmatch автоматом дропнутся (init-скриптbackend/db/init/99_drop_unused_extensions.sql)
Sensitive операционные грабли
docker compose restartНЕ перечитываетenv_file:— после правкиbackend/.envвсегдаdocker compose -f docker-compose.prod.yml up -d --force-recreate --no-deps backenddeploy.ymlиспользуетgit reset --hard origin/main— любые ручные правки в/opt/gendesignбудут стёрты при следующем деплое..envфайлы переживут (в.gitignore)docker compose upбез-f docker-compose.prod.ymlна проде поднимет dev compose (с локальной сборкой образов и без Caddy). Признаки:Image ... Builtв выводе и WARN про orphan caddy. Всегда указывай-fcaddy reloadне сбрасывает retry-queue. Если Caddy пытался получить cert для несуществующего hostname (например, плейсхолдера из старого Caddyfile), фоновые попытки могут переключить его в Let's Encrypt staging fallback. Рецепт чистого старта:docker volume rm gendesign_caddy_data && docker compose up -d caddy
GitHub Actions deploy
Workflow .github/workflows/deploy.yml:
- Build обоих Docker-образов (backend ~2.5 мин с нуля, frontend ~1 мин с нуля; повторно из кеша — секунды)
- Push в GHCR (
ghcr.io/lekss361/gendesign-backend,gendesign-frontend) с тегамиlatestи<sha7> - SSH deploy:
docker compose -f docker-compose.prod.yml pull && up -d, потомcurl /health
GitHub Secrets (Settings → Secrets and variables → Actions):
| Имя | Значение |
|---|---|
DEPLOY_HOST |
46.173.16.127 |
DEPLOY_USER |
gendesign |
DEPLOY_SSH_KEY |
приватный ключ ~/.ssh/gendesign_deploy целиком |
DEPLOY_PORT |
22 (или другой, если поменяли) |
GITHUB_TOKEN встроенный — отдельный secret для push в GHCR не нужен.
Авторизация сервера в GHCR (приватные пакеты):
Сервер авторизуется однократно через PAT с read:packages:
# На сервере, как пользователь gendesign
read -s GHCR_PAT && echo "$GHCR_PAT" | docker login ghcr.io -u lekss361 --password-stdin && unset GHCR_PAT
Auth сохраняется в ~/.docker/config.json и переживает рестарт. Ротировать PAT раз в год.
Память проекта (knowledge graph)
Все решения, факты, риски, KPI, протоколы валидации хранятся только в графе памяти, не в .md-документах. Это решает проблему расхождения версий между документами.
Как устроено:
- MCP-сервер
mcp-knowledge-graphпишет вC:\mcp\.aim\memory-gendesign.jsonl - Этот файл — хард-линк на
<repo>/memory/memory-gendesign.jsonl - Изменения попадают в git автоматически
- Синхронизация между коллегами — через
git pull/git push
Правило проекта (Feedback_MemoryFirst):
- Все факты и решения сохраняем в граф (
context: "gendesign") .md/.docx/.pdfClaude не создаёт сам — только по явному запросу- Источник правды = граф, документы = производные срезы
Рабочий цикл:
git pull # перед началом работы
# ... сессия с Claude ...
git add memory/memory-gendesign.jsonl
git commit -m "Memory: <что добавили>"
git push
Конфликты в .jsonl обычно простые (файл построчный): git pull --rebase, оставить обе стороны, git rebase --continue.
Подключение коллеги
Краткая инструкция для нового участника команды:
- Установить Claude Desktop, Node.js 20+, Git
- Клонировать репо в
C:\Users\<имя>\source\repos\gendesign mkdir C:\mcp\.aim- Создать хард-линк:
New-Item -ItemType HardLink ` -Path C:\mcp\.aim\memory-gendesign.jsonl ` -Value $PWD\memory\memory-gendesign.jsonl - Добавить в
%APPDATA%\Claude\claude_desktop_config.json:"knowledge-graph": { "command": "npx", "args": ["-y", "mcp-knowledge-graph", "--memory-path", "C:\\mcp\\.aim"] } - Перезапустить Claude Desktop полностью (через трей)
- Проверить: «Покажи память контекста gendesign»
Полная версия процедуры — в графе, сущность Onboarding_Colleague_KG.
Документы стратегии
В docs/:
MVP_Goals_Python.md— цели Discovery MVP, Python-стек (v2.2, апрель 2026)Бизнес-план v2.1 - Site Finder + Roadmap 12 месяцев.md— бизнес-план
⚠️ Эти документы — снимок состояния на момент написания. Свежее состояние стратегии — в графе памяти. При расхождении доверяем графу.
Релевантные сущности графа на 26.04.2026:
Стратегия / план:
Project_GenDesign— общая шапкаTechStack_v2.2— Python + Next.js стекNorthStar_DiscoveryMVP— 3 пилота + реестр ПО → Раунд АStages_MVP_v1— базовая разбивка по этапамTeam_Setup— 2 фуллстека part-timeWorkSplit_Generative_Stage1— кто что делает в GenerativePlanA_AnalyticsFirst_Apr25— pending pivot решение (ждём 27.04 — Антон по ДДУ)SalesTracking_Strategy_Apr25— шахматки застройщиковDataSources_Pricing_Apr25— источники цен и площадейValidation_Findings_Apr25— валидация бизнес-плана
Инфраструктура:
Hosting_Pricing_Apr25— сравнение провайдеровHosting_Decision_Apr25— решение по Yandex Cloud (для будущей миграции)Runbook_VPS_Setup_Beget— пошаговая настройка production VMSSH_Setup_Apr25— локальная настройка SSHDockerOps_Apr26— multi-stage Dockerfile, npm ci, healthcheck fix, same-origin APIProduction_Wipe_Apr26— clean re-deploy с нуля (event)Domain_Setup_Apr26— gendsgn.ru, Beget, DNS, ESIA-правилоSentry_Setup_Apr26— проект, DSN, тестовое событиеOpsBundle_Apr26— Alembic + TIGER cleanup + pre-commit + pg_dumpHTTPS_Live_Apr26— milestone: HTTPS прод заработал (включая lessons learned по ACME retry-state)
Процесс / правила:
Onboarding_Colleague_KG— подключение нового участника к графуFeedback_MemoryFirst— правило: память first, docs только по запросу
Полезные ссылки
- 🌐 Production: https://gendsgn.ru/
- 🩺 Health: https://gendsgn.ru/health
- 📚 OpenAPI: https://gendsgn.ru/openapi.json · Swagger UI
- Репо: https://github.com/lekss361/-gendesign
- Issues backlog: https://github.com/lekss361/-gendesign/issues
- Milestones: https://github.com/lekss361/-gendesign/milestones
- GitHub Actions: https://github.com/lekss361/-gendesign/actions
- GHCR пакеты: https://github.com/lekss361?tab=packages
- Sentry: https://qqq-5y.sentry.io/insights/projects/gendesign-backend/
- Production VPS: Beget Cloud →
cp.beget.com/cloud/servers/jolly-yakov-3 - DNS-панель домена: https://cp.beget.com/dns/14193206
- Целевой регион Discovery: Свердловская обл. (Екатеринбург, ПЗЗ, МСК-66)
- Конкуренты: rTIM (только концепт-стадия, нет site-selection), TestFit (нет РФ-данных)