diff --git a/README.md b/README.md index 45eb8029..9c74d52f 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,34 @@ Acceptance criteria разбиты на 3 блока (функционально --- +## Текущий статус (25 апреля 2026) + +**Инфраструктура: live.** Полный цикл автодеплоя из GitHub Actions работает. + +| Что | Где | Статус | +|---|---|---| +| Production VPS | Beget Cloud, Москва, 2 vCPU / 4 GB / 40 GB NVMe | ✅ работает | +| IP сервера | `46.173.16.127` | — | +| Postgres + PostGIS 3.4 | Docker, в составе compose | ✅ Up (healthy) | +| Redis 7 | Docker | ✅ Up | +| Backend FastAPI | Docker (образ из GHCR) | ✅ Up, `/health` отвечает | +| Frontend Next.js 15 | Docker (образ из GHCR) | ✅ Up | +| Caddy reverse proxy | Docker, ports 80/443 | ✅ Up (TLS ждёт домена) | +| GitHub Actions deploy | `.github/workflows/deploy.yml` | ✅ build → push GHCR → ssh deploy | +| GHCR пакеты | `ghcr.io/lekss361/gendesign-{backend,frontend}` | приватные, сервер авторизуется через PAT | +| UFW firewall | 22 / 80 / 443 | ✅ активен | +| SSH hardening | root login off, password auth off | ✅ | +| Домен | — | ⏸ не подключён | +| Бэкапы pg_dump | — | ⏸ не настроены | + +**Решение по плану разработки: 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` в графе памяти. + +--- + ## Структура репозитория ``` @@ -33,6 +61,7 @@ gendesign/ ├── 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 @@ -40,13 +69,14 @@ gendesign/ ├── memory/ │ └── memory-gendesign.jsonl # хард-линк на C:\mcp\.aim — общий граф памяти ├── docs/ # стратегические документы (бизнес-план, цели MVP) +├── .env.example # шаблон prod env (POSTGRES_*, IMAGE_TAG, NEXT_PUBLIC_API_BASE_URL) ├── docker-compose.yml # dev: Postgres + Redis + backend + frontend -├── docker-compose.prod.yml # prod: образы из реестра + Caddy reverse-proxy +├── docker-compose.prod.yml # prod: образы из GHCR + Caddy + Postgres+Redis ├── Caddyfile # авто-TLS Let's Encrypt ├── Makefile # make up / down / test / codegen / migrate └── .github/workflows/ ├── ci.yml # ruff + mypy(core) + pytest + frontend build - └── deploy.yml # build → push в реестр → ssh deploy на VM + └── deploy.yml # build → push в GHCR → ssh deploy на VM ``` --- @@ -57,7 +87,7 @@ gendesign/ **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) +**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, ruff, mypy (strict только на core), pytest @@ -74,27 +104,29 @@ gendesign/ - Trunk-based: feature ветки ≤ 3 дней - Codegen TS-типов из Pydantic (`npm run codegen`) — без этого 2 фуллстека плодят расхождения в API-контракте -**Порядок:** строго последовательный — Generative полностью, потом Site Finder. - --- -## Этапы MVP (12 недель) +## Этапы 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` до Раунда А). +### 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) +### 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. Это уже **продаваемый артефакт** — можно показывать на встречах с месяца 2. +**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. +- **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 → перед Раундом А @@ -111,6 +143,7 @@ gendesign/ # 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 @@ -128,7 +161,7 @@ curl http://localhost:8000/health ```bash make logs # tail логов всех сервисов make backend-shell # bash внутри backend контейнера -make migrate # alembic upgrade head +make migrate # alembic upgrade head (когда добавим миграции) make test # pytest make lint # ruff check make typecheck # mypy на core @@ -137,23 +170,19 @@ make codegen # обновить TS-типы из OpenAPI --- -## Хостинг (production) +## Production хостинг — Beget VPS -### Discovery MVP (мес. 1–3): минимальный режим +**Текущая live-конфигурация:** Beget Cloud, Москва, Standard 3+ GHz, 2 vCPU / 4 GB / 40 GB NVMe. -**1× VPS** на Selectel / Timeweb / Beget (2 vCPU / 4 GB / 60 GB SSD), всё в Docker Compose: +**Стоимость:** ~33 ₽/день сервер + ~5 ₽/день IPv4 = **~1140 ₽/мес**. Плюс домен .ru (~17 ₽/мес). -| Компонент | Сервис | -|---|---| -| App | backend + frontend (образы из GHCR) | -| БД | Postgres 16 + PostGIS 3.4 (в том же compose) | -| Кэш/очереди | Redis 7 | -| TLS | Caddy с Let's Encrypt автоматически | -| Бэкапы | cron pg_dump → Yandex Object Storage (free tier 1 GB) | +**Что крутится на 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` -**Стоимость:** ~1300–2000 ₽/мес (VPS) + ~17 ₽/мес (домен .ru) = **~1500–2000 ₽/мес**. - -⚠️ **Критично:** настроить ежесуточный pg_dump в первую неделю. Без бэкапа = смерть проекта при первом сбое VM. +**Доступ:** SSH-only по ключу к non-root пользователю `gendesign`. Root login отключён, password auth отключён, fail2ban Beget активен. ### Триггеры миграции на Yandex Cloud @@ -165,17 +194,44 @@ make codegen # обновить TS-типы из OpenAPI Стоимость production на YC: ~10–15 тыс ₽/мес. -### GitHub Actions deploy +### Что осталось до «infra-ready» -Workflow `.github/workflows/deploy.yml` собирает образы и через SSH деплоит на VM: -1. Build backend + frontend Docker образов -2. Push в реестр (GHCR для Discovery, YCR после миграции) -3. SSH на VM → `docker compose pull && up -d` +- [ ] Купить домен .ru (REG.RU / РуЦентр), направить A-запись на `46.173.16.127` +- [ ] Обновить `Caddyfile` с реальным доменом → авто-TLS Let's Encrypt +- [ ] Задать `NEXT_PUBLIC_API_BASE_URL=https://<домен>` в `/opt/gendesign/.env` либо оставить пустым (frontend ходит через Caddy `/api/*` → backend) +- [ ] Настроить ежесуточный `pg_dump` → Object Storage (Yandex free tier 1 GB или Selectel S3) +- [ ] Sentry DSN в `backend/.env` -**Secrets** (GitHub → Settings → Secrets and variables → Actions): -- `DEPLOY_HOST`, `DEPLOY_USER`, `DEPLOY_SSH_KEY`, `DEPLOY_PORT` (опц.) -- Для GHCR — `GITHUB_TOKEN` встроенный, отдельный secret не нужен -- Для YC (после миграции) — `YC_SA_JSON_CREDENTIALS`, `YC_REGISTRY_ID` +--- + +## GitHub Actions deploy + +Workflow `.github/workflows/deploy.yml`: +1. **Build** обоих Docker-образов (backend ~2.5 мин с нуля, frontend ~1 мин с нуля; повторно из кеша — секунды) +2. **Push** в GHCR (`ghcr.io/lekss361/gendesign-backend`, `gendesign-frontend`) с тегами `latest` и `` +3. **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`: + +```bash +# На сервере, как пользователь gendesign +read -s GHCR_PAT && echo "$GHCR_PAT" | docker login ghcr.io -u lekss361 --password-stdin && unset GHCR_PAT +``` + +Auth сохраняется в `~/.docker/config.json` и переживает рестарт. Ротировать PAT раз в год. --- @@ -207,7 +263,7 @@ git push ### Подключение коллеги -Краткая инструкция для нового участника команды (полная версия — у владельца репо): +Краткая инструкция для нового участника команды: 1. Установить Claude Desktop, Node.js 20+, Git 2. Клонировать репо в `C:\Users\<имя>\source\repos\gendesign` @@ -228,6 +284,8 @@ git push 6. Перезапустить Claude Desktop полностью (через трей) 7. Проверить: «Покажи память контекста gendesign» +Полная версия процедуры — в графе, сущность `Onboarding_Colleague_KG`. + --- ## Документы стратегии @@ -238,10 +296,31 @@ git push ⚠️ Эти документы — **снимок состояния на момент написания**. Свежее состояние стратегии — в графе памяти. При расхождении доверяем графу. +Релевантные сущности графа на 25.04.2026: +- `Project_GenDesign` — общая шапка +- `TechStack_v2.2` — Python + Next.js стек +- `NorthStar_DiscoveryMVP` — 3 пилота + реестр ПО → Раунд А +- `Stages_MVP_v1` — базовая разбивка по этапам +- `Team_Setup` — 2 фуллстека part-time +- `WorkSplit_Generative_Stage1` — кто что делает в Generative +- `PlanA_AnalyticsFirst_Apr25` — pending pivot решение +- `SalesTracking_Strategy_Apr25` — шахматки застройщиков +- `DataSources_Pricing_Apr25` — источники цен и площадей +- `Hosting_Pricing_Apr25` — сравнение провайдеров +- `Hosting_Decision_Apr25` — решение по Yandex Cloud (для будущей миграции) +- `Runbook_VPS_Setup_Beget` — пошаговая настройка production VM +- `SSH_Setup_Apr25` — локальная настройка SSH +- `Onboarding_Colleague_KG` — подключение нового участника к графу +- `Feedback_MemoryFirst` — правило: память first, docs только по запросу +- `Validation_Findings_Apr25` — валидация бизнес-плана + --- ## Полезные ссылки - **Репо:** https://github.com/lekss361/-gendesign +- **GitHub Actions:** https://github.com/lekss361/-gendesign/actions +- **GHCR пакеты:** https://github.com/lekss361?tab=packages +- **Production VPS:** Beget Cloud → `cp.beget.com/cloud/servers/jolly-yakov-3` - **Целевой регион Discovery:** Свердловская обл. (Екатеринбург, ПЗЗ, МСК-66) - **Конкуренты:** rTIM (только концепт-стадия, нет site-selection), TestFit (нет РФ-данных) diff --git a/memory/memory-gendesign.jsonl b/memory/memory-gendesign.jsonl index dacce1c7..656b8efa 100644 --- a/memory/memory-gendesign.jsonl +++ b/memory/memory-gendesign.jsonl @@ -5,16 +5,29 @@ {"type":"entity","name":"Phase0_DiscoveryMVP","entityType":"phase","observations":["Discovery MVP, месяцы 1–3 после старта","Пилотный регион: Свердловская обл. (Екатеринбург, ПЗЗ Екатеринбурга, МСК-66)","Месяц 1 цели: ООО зарегистрировано, прототип Site Finder с 1000 участков, 50 целевых клиентов в CRM, 5 cold-outreach, 3 встречи","Месяц 2 цели: 15 встреч кумулятивно, 2 LOI, 1 платящий пилот (≥30 тыс. ₽/мес), демо на реальных участках, первая статья","Месяц 3 цели: 20+ встреч, 3 платящих пилота, 7+ LOI, 1 регадминистрация в переговорах, заявка в реестр ПО, инвест-deck (12 слайдов), финмодель на 5 лет"]} {"type":"entity","name":"Validation_Findings_Apr25","entityType":"review","observations":["Дата валидации: 25 апреля 2026","КРИТИЧНО: бизнес-план v2.1 не синхронизирован со стеком v2.2 — в плане 12 мес. месяцы 1–4 ещё ссылаются на .NET Core 8","Несостыковка KPI: v2.1 = 4 платящих пилота, v2.2 = 3 — нужно остановиться на 3 (как в Acceptance Criteria v2.2)","Регион не зафиксирован однозначно: v2.1 пишет «Свердл. или Лен.», v2.2 — только Свердл. — закрепить Свердловскую","Прайсинг: пилот 30 тыс., прайс-лист 70–120 тыс. — уточнить в финмодели для инвесторов: 70 тыс./мес как baseline","Технические риски: Time to First Value ≤10 мин амбициозно (предложение: 15 мин); генерация концепции ≤10 сек требует профилировки с первого билда","PostgreSQL TDE отсутствует в open-source — заменить на pgcrypto + шифрование чувствительных полей на уровне приложения","mypy --strict для всего MVP избыточен соло-разработчику — оставить только для core-модулей (geometry/scoring/financial)","99% uptime в рабочие часы для соло-разработчика рискованно — реалистично 95% + ответ в течение рабочего дня","Заявка в реестр ПО ≠ свидетельство; срок рассмотрения 60–180 дней — учесть для расчёта Раунда А","Бюджет 1,2 млн ₽ + 3 мес. + один основатель плотный; рекомендация — заложить буфер +1 месяц или урезать DXF-экспорт из Discovery"]} {"type":"entity","name":"Feedback_MemoryFirst","entityType":"feedback","observations":["Правило: вся информация по проекту gendesign хранится в memory-gendesign.jsonl (context=\"gendesign\"). Информация = факты, решения, результаты анализа, обсуждения стратегии, KPI, списки рисков, протоколы валидации и т.д.","НИКОГДА не создавать .md / .docx / .pdf / .pptx файлы самостоятельно — даже если кажется, что это поможет. Документы генерируются ТОЛЬКО по явному запросу («сделай md», «собери в документ», «выгрузи в docx»).","При поступлении новых фактов/решений в разговоре — сразу сохраняем в память через aim_memory_store / aim_memory_add_facts в context=\"gendesign\".","Для файловой генерации по запросу: запрос срез из памяти (aim_memory_search/read_all) → сборка документа. Память = единый источник правды, файлы = производные.","**Why:** пользователь хочет избежать разъехавшейся инфы между версиями доков (как случилось с v2.1/v2.2). Единый источник (граф памяти) — синхронен по определению.","**How to apply:** в любом обмене по этому проекту — (1) сначала читаем gendesign-память, (2) ведём диалог/анализ, (3) сохраняем новые выводы в память, (4) файлы только если пользователь явно запросил."]} -{"type":"entity","name":"MemoryAutoSync_macOS_Apr25","entityType":"infrastructure","observations":["Дата настройки: 25 апреля 2026, машина anton@macOS (/Users/anton)","Цель: автоматическая двусторонняя синхронизация файла графа памяти ~/.aim/memory-gendesign.jsonl с веткой main репо lekss361/-gendesign на GitHub","Хард-линк: ~/.aim/memory-gendesign.jsonl и ~/source/repos/gendesign/memory/memory-gendesign.jsonl — один inode, link count = 2. Любая запись MCP-сервера видна в git status мгновенно","Git auth: credential.helper=osxkeychain (глобально), токен github.com сохранён в Login Keychain под аккаунтом Light1YT — push идёт без интерактива","Sync agent (push): launchd job com.gendesign.memory-sync, plist в ~/Library/LaunchAgents/com.gendesign.memory-sync.plist, скрипт ~/.aim/gendesign-memory-sync.sh. Триггер: WatchPaths на файле памяти. Дебаунс: ThrottleInterval=60с. Логика: проверка целостности хард-линка → git pull --rebase --autostash → парсинг diff и сборка content-aware commit message → git commit → git push origin main","Pull agent: launchd job com.gendesign.memory-pull, plist в ~/Library/LaunchAgents/com.gendesign.memory-pull.plist, скрипт ~/.aim/gendesign-memory-pull.sh. StartInterval=120с + RunAtLoad=true. Делает git pull --rebase --autostash, лог только при реальных изменениях; чинит хард-линк если порвался","Commit message format: 'Memory: ()'. Summary включает +ent/~ent/-ent (новая/изменённая/удалённая сущность) и +rel/-rel (связи). Парсер на python3 встроен в sync-скрипт","Защита от atomic-rewrite MCP-сервера: оба скрипта проверяют stat -f %i у обоих файлов; если inode разошлись — копируют контент из репо в ~/.aim и пере-создают хард-линк","Логи: ~/.aim/gendesign-sync.log (sync trigger лог), ~/.aim/gendesign-sync.launchd.log (stderr launchd для sync), ~/.aim/gendesign-pull.log (pull лог только при изменениях), ~/.aim/gendesign-pull.launchd.log (stderr launchd для pull)","Управление: launchctl load/unload для включения/выключения; launchctl list | grep gendesign — статус; tail -f ~/.aim/gendesign-*.log — мониторинг","Ручное вмешательство нужно только при merge-конфликте jsonl (две машины правили одну сущность одновременно) — лог покажет 'pull --rebase failed', чинится руками в репо","Не реализовано: автоматический pull в момент чтения памяти Claude Desktop (он читает текущий файл, может быть отстающим до 120с от удалённой ветки); нет защиты от чужих незакоммиченных правок в memory/ перед auto-commit (autostash спасает только от своих локальных)"]} -{"type":"entity","name":"MVP_Scope_AreaSelect_Apr25","entityType":"decision","observations":["Дата решения: 25 апреля 2026","Сценарий MVP-приложения: на конкретном выбранном участке пользователь выделяет (рисует) область → приложение генерирует варианты: концепции застройки (ген.планы), финансовые модели и др. — каждый вариант с оценкой/рейтингом","Сужает MVP scope относительно two-in-one воронки из Project_GenDesign: Discovery MVP фокусируется на стадии 'участок известен → область выделена → концепт + финмодель + оценка', а не на полной цепочке 'инвест-критерии → Site Finder → концепт → финмодель'","Связанные UX-элементы: карта (Mapbox/Leaflet) с выбором участка, инструмент рисования полигона (выделение области), кнопка 'сгенерировать варианты', список/грид вариантов с оценками, детальный view по выбранному варианту (генплан визуально + финмодель в таблице/графиках)","Решено (Site Finder): откладывается в Пост-MVP. Discovery MVP фокус — генерация вариантов на уже выбранном участке. Импликация для Phase0_DiscoveryMVP: M1-цель 'прототип Site Finder с 1000 участков' переориентируется на pipeline 'участок → область → 3 варианта → PDF' на 5–10 демо-участках","Решено (формат выдачи): двухэтапный. Этап 1 (ранний MVP) — PDF-отчёт с генпланом и финмоделью (WeasyPrint с первого билда). Этап 2 (поздний MVP / след итерация) — интерактивный просмотр вариантов на карте (Mapbox/Leaflet)","Решено (метрики оценки): референс — TestFit (https://www.testfit.io/). Стартовый набор метрик (в стиле TestFit, адаптировать под РФ): buildable area, GFA / NSF, количество юнитов, unit mix, parking count + ratio, hard cost / soft cost / total cost, выручка (продажа или аренда), доходность (IRR / ROI / yield), проверка соответствия ПЗЗ (рос аналог zoning). Финальный список — после изучения TestFit demo и первого пилота","Решено (источники данных об участке): поддерживаем все источники на минимально-полном уровне: ПЗЗ Екб, кадастр (КН), пользовательская загрузка GeoJSON/KML. 'Минимально-полный' = достаточно для 1–2 демо-сценариев в каждом источнике, без полной автоматизации всех граничных случаев","Решено (число вариантов): 3 варианта на генерацию (фиксированно в MVP). API возвращает массив длины 3, фронт показывает 3-карточный грид. Бюджет времени на генерацию: ≤10 сек (требование из Validation_Findings_Apr25 — требует профилировки с первого билда), распределяется на 3 варианта параллельно — ограничение сложности алгоритма каждого"]} +{"type":"entity","name":"Team_Setup","entityType":"team","observations":["2 фуллстек-разработчика (оба пишут Python + TypeScript)","Оба part-time по 20 ч/неделю — итого ~40 person-hours/неделю (эффективных с координацией ~33)","Разделение по фичам, а не по слоям — оба трогают backend и frontend","Ритм координации: 1 синк/неделю (30 мин), daily-async в Telegram, PR review обязательный","Ветвление: trunk-based, feature ветки ≤ 3 дней","Критичный тулинг: openapi-typescript для codegen TS-типов из Pydantic-схем (иначе два фуллстека плодят расхождения в API-контракте)"]} +{"type":"entity","name":"Stages_MVP_v1","entityType":"plan","observations":["Порядок: строго последовательный — Generative полностью, потом Site Finder","Общая оценка: 12 недель (Stage 0: 1 нед., Stage 1: 6 нед., Stage 2: 5 нед.)","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 до Раунда А)","Stage 1a (нед. 2-3) — геометрия + API-контракт. A: Shapely-сервис (отступы, сетка), Pydantic ConceptInput/Output, POST /api/v1/concepts с заглушкой. B: страница /concept, Leaflet, импорт GeoJSON + отрисовка, форма параметров, вывод 3 вариантов в табах","Stage 1b (нед. 4-5) — алгоритм размещения. A: жадное заполнение, 3 стратегии, STRtree для коллизий, профилировка (цель ≤10с, fallback 15с). B: визуализация корпусов, метрики ТЭП, сравнение вариантов","Stage 1c (нед. 6-7) — ТЭП + финмодель + экспорты. A: teap.py, financial.py, openpyxl. B: WeasyPrint шаблон, ezdxf, UI кнопок скачивания","Acceptance Stage 1 (конец нед. 7): полигон→3 варианта→ТЭП+финмодель→PDF/Excel/DXF. Продаваемый артефакт для встреч с месяца 2","Stage 2a (нед. 8-9) — data pipeline. A: парсер ПКК Rosreestr (httpx async, retries), модель Parcel с GeoAlchemy2, загрузка 1000+ участков Екбурга. B: Overpass API для POI, ДОМ.РФ/ЦИАН для цен м², кеш в Redis","Stage 2b (нед. 10-11) — скоринг+API+UI. A: 3 критерия скоринга (эвристики, без XGBoost), POST /parcels/search. B: страница /site-finder, Mapbox, градация по рейтингу, фильтры, карточка","Stage 2c (нед. 12) — интеграция + полировка. Кнопка «Обсчитать концепцию», демо-наполнение 50 участков, бэкапы БД, подача в реестр ПО","Урезано из v2.2 из-за part-time ×2: XGBoost→Фаза 1, JWT-auth→перед Раундом А, mypy --strict только на core, время генерации ≤15с (а не 10с) как fallback"]} +{"type":"entity","name":"Hosting_Decision_Apr25","entityType":"decision","observations":["Дата: 25 апреля 2026","Выбор хостинга для РФ: рассматривались Yandex Cloud, VK Cloud, Selectel, Timeweb Cloud, Cloud.ru (Сбер)","Рекомендован Yandex Cloud как основной вариант для Discovery + Production","Обоснование: (1) лучшая поддержка PostGIS в Managed PostgreSQL в РФ; (2) Container Registry + Container Solution включены; (3) входит в реестр российского ПО — плюс к нашей заявке; (4) солидно выглядит для инвесторов Раунда А","Стоимость Discovery (~10–15 тыс ₽/мес): VM Compute s3-c2-m4 (~3-4 тыс), Managed Postgres 1vCPU/4GB/30GB SSD (~5-7 тыс), Container Registry (бесплатно до 5GB), Object Storage для бэкапов (~500₽)","Альтернатива для жёсткой экономии: Selectel дешевле в 1.5–2 раза, но требует ручной PostGIS-рутины. Резерв на случай проблем с YC","Архитектура production: 1×VM с Docker Compose (backend + frontend + Caddy reverse proxy + auto-TLS) + Managed PostgreSQL (отдельный сервис) + Object Storage (бэкапы)","Образы: backend + frontend пушатся в Yandex Container Registry из GitHub Actions; на VM выполняется docker compose pull && up -d","GitHub Secrets для deploy: YC_SA_JSON_CREDENTIALS, YC_REGISTRY_ID, DEPLOY_HOST, DEPLOY_USER, DEPLOY_SSH_KEY, DEPLOY_PORT (опционально)","Caddy выбран вместо nginx: авто-TLS через Let's Encrypt без ручных certbot-рутин — дешевле по времени сопровождения для part-time команды","Домен: покупать в .ru зоне (REG.RU или РуЦентр), DNS на Yandex Cloud DNS или Cloudflare бесплатный","Production-путь на VM: /opt/gendesign/docker-compose.prod.yml + .env + Caddyfile"]} +{"type":"entity","name":"Onboarding_Colleague_KG","entityType":"procedure","observations":["MCP-сервер для памяти: npm-пакет mcp-knowledge-graph (запуск через npx -y)","Команда в claude_desktop_config.json: command=npx, args=['-y','mcp-knowledge-graph','--memory-path','<путь к папке с .jsonl файлами>']","Путь в рабочей среде основателя: C:\\mcp\\.aim","Стратегия разделённой памяти между коллегами: git синхронизация файла memory-gendesign.jsonl + хард-линк из репо в MCP-папку. Источник правды — репо","Конфликты в .jsonl обычно простые (файл построчный): решаются выбором \"оставить обе стороны\". rebase, не merge","Ритуал: git pull перед началом работы, git commit+push после изменений памяти","Полный текст процедуры выдан в чате 25 апреля 2026; при повторном запросе — восстановить из этой сущности"]} +{"type":"entity","name":"Hosting_Pricing_Apr25","entityType":"research","observations":["Дата проверки: 25 апреля 2026, фактические цены с сайтов провайдеров","Целевой конфиг: 2 vCPU / 4 GB RAM / 30-40 GB NVMe SSD + public IPv4. 60 GB избыточен для Discovery (реальное использование диска 12-15 GB: OS+Docker 5-7 GB + Postgres+PostGIS 0.5-1 GB + логи+бэкапы 1-2 GB + буфер 5 GB)","Selectel Standard Line 2/4 GB = 2308.86 ₽/мес (CPU+RAM only) + диск 30 GB Network SSD ~270 ₽ + public IP. Итого ~2700-3000 ₽/мес. Дороже конкурентов в 2-3 раза","Selectel Shared Line 2/4 GB с 10% vCPU = 1239 ₽/мес — дешевле, но CPU слишком слабый для Postgres+PostGIS под реальной нагрузкой","Timeweb Cloud MSK 50: 2 vCPU 3.3 GHz / 4 GB / 50 GB NVMe / 1 Гбит/с = 1062 ₽/мес со скидкой 10% при годовом контракте (или ~1180 ₽ без контракта). IPv4 включён. Реестр ПО № 15725","Beget VPS Standard 2 vCPU 3+ GHz / 4 GB / 40 GB NVMe = 33 ₽/день сервер + 5 ₽/день IPv4 = 38 ₽/день ≈ 1140 ₽/мес. Автобэкапы раз в несколько дней бесплатно. KVM. Реестр ПО № 16697","Beget VPS 2/2/30 = 27 ₽/день + 5 ₽ IP = 32 ₽/день ≈ 960 ₽/мес — ещё дешевле, но 2 GB RAM маловато для Postgres+PostGIS+Redis+backend+frontend+Caddy","Рекомендация Discovery: Beget VPS 2/4/40 NVMe + IP ≈ 1140 ₽/мес (самый дешевый реально рабочий конфиг) или Timeweb Cloud MSK 50 ≈ 1062 ₽/мес (лучше NVMe, больше диск)","Ранее в Hosting_Decision_Apr25 был предложен Yandex Cloud (~10-15 тыс ₽/мес с managed services). Это вариант для продакшена после Раунда А, не для Discovery","Для Discovery Beget выигрывает по цене и бесплатным бэкапам. Timeweb выигрывает по UI/UX панели и большему диску. Selectel оправдан только если планируется быстрый перевод на managed Postgres/K8s в их экосистеме"]} +{"type":"entity","name":"SSH_Setup_Apr25","entityType":"infrastructure","observations":["SSH-ключ для проекта: ed25519, без passphrase (для автодеплоя из GitHub Actions)","Локация: $HOME\\.ssh\\gendesign_deploy (приватный) + .pub (публичный)","Comment ключа: 'gendesign-deploy'","SSH config alias: 'Host gendesign' с IdentityFile ~/.ssh/gendesign_deploy — коннект командой 'ssh gendesign'","Публичный ключ вручную загружается в панель хостинг-провайдера при создании сервера","Приватный ключ позже пойдёт в GitHub Secret DEPLOY_SSH_KEY (для deploy.yml workflow)","Windows-специфика: icacls нужен для ограничения прав на приватный ключ, иначе OpenSSH ругается на 'UNPROTECTED PRIVATE KEY FILE'"]} +{"type":"entity","name":"WorkSplit_Generative_Stage1","entityType":"plan","observations":["Принцип разделения: вертикальные срезы по этапам пользовательского пути, не по слоям","Person A — 'Geometry → Variants' owner: Shapely-сервис, нормативные отступы, жадный алгоритм с 3 стратегиями, STRtree коллизии, профилировка. API endpoint POST /concepts, владелец схемы ConceptInput+buildings_geojson. Фронт: Leaflet, импорт/отрисовка полигона, форма параметров, рендеринг 3 вариантов на карте","Person B — 'Variants → Reports' owner: TEAP-сервис, финансовая модель, экспорты PDF/Excel/DXF (WeasyPrint+openpyxl+ezdxf). API endpoint /concepts/:id/export, владелец схем TEAP+FinancialModel. Фронт: таблицы ТЭП, форма финмодели, кнопки скачивания, сравнение вариантов","Точка стыка = Pydantic-контракт ConceptVariant в backend/app/schemas/concept.py. Договариваются в первый день Stage 1a, дальше оба работают с заглушками друг друга без блокировки","Точка стыка 2 — codegen TS-типов: при любой правке схемы оба запускают 'npm run codegen' локально","Календарь по неделям (Stage 1, нед.2-7): A движется по вектору схема→отступы→алгоритм→стратегии→тесты. B движется по вектору схема→TEAP→financial→Excel→DXF→PDF→тесты","Альтернативный расклад при асимметрии навыков: Алгоритмист (A) берёт все 4 backend-сервиса (geometry+TEAP+financial+exporters), фронт минимум. Продуктовик (B) берёт весь фронт + UI экспортов, backend минимум (тонкий export endpoint)","Анти-паттерны: разделение backend/frontend (блокирует второго), общие прямые пуши в main, молчаливые правки Pydantic без codegen, pair programming на каждой задаче (дорого для part-time ×2)"]} +{"type":"entity","name":"DataSources_Pricing_Apr25","entityType":"research","observations":["Дата: 25 апреля 2026","В РФ открытых данных по реальным сделкам (Росреестр) НЕТ — только агрегаты. Цены и площади из агрегаторов (ЦИАН/ДомКлик/Авито) — по объявлениям, не по сделкам","Открытые официальные источники (бесплатно, без юрриска): ДОМ.РФ (наш.дом.рф + api.dom.rf, реестр новостроек, площади в жк, колво квартир по комнатностям, класс жилья); Росстат (fedstat.ru, средние цены м² по регионам квартально); Минстрой (норматив цены м² для субсидий); Главгосэкспертиза НЦС (gge.ru, себестоимость м² строительства)","Скрейпинг агрегаторов (серая зона): ЦИАН (cianparser/cianscraper либы на GitHub, но Cloudflare и рейтлимит); Авито; ДомКлик; Яндекс.Недвижимость. Юридически — нарушение ТОС, но исков против мелких парсеров немного","Платные отраслевые: ЕРЗ.РФ Премиум (50-100тыс ₽/год, отраслевой стандарт); Knight Frank/NF Group/CBRE отчеты; PROEstate Analytics; СберИндекс (бесплатно)","Industry-standard unit-mix (из практики): Студии/1к/2к/3к/4+к по классам. Эконом: 15-20/35-40/25-30/10-15/0-5%. Комфорт: 8-12/25-30/30-35/20-25/5-10%. Бизнес: 5-10/18-22/30-35/25-30/10-15%. Премиум: 0-5/10-15/30/30-35/20-25%","Средние площади квартир м² (студия/1к/2к/3к): Эконом 22-28/33-38/50-58/70-80; Комфорт 26-30/38-44/58-66/80-92; Бизнес 30-35/45-55/70-85/100-125; Премиум 35-45/55-70/90-110/130-180. Нормативная нижняя граница — СП 54.13330.2016","Рекомендация для Discovery: Цены — Росстат baseline + ручной парсинг/скрейп ЦИАН 200 объявлений по районам Екбурга. Площади+unit-mix — захардкодить таблицу с возможностью ручной правки. Себестоимость — НЦС Главгосэкспертизы. Новостройки-конкуренты — API ДОМ.РФ","Для реестра ПО декларируем только легальные источники: ДОМ.РФ, Росстат, Главгосэкспертиза, OpenStreetMap. Скрейп ЦИАН — «внутренний справочник curating». Для инвесторов Раунда А — «договорённости с источниками рыночных данных в проработке»"]} +{"type":"entity","name":"SalesTracking_Strategy_Apr25","entityType":"strategy","observations":["Дата анализа: 25 апреля 2026","Исходный вопрос: можно ли косвенно понять, какие квартиры продаются и какие нет. Ответ: да, через ejednevnyy мониторинг шахматок застройщиков + delta-tracking","Прямые данные о сделках в РФ закрыты: Росреестр ДДУ не в open data, нотариусы и банки — закрытые источники","Косвенные источники по точности: 1) Шахматки застройщиков — 95%+ точность, золотая жила. 2) ДОМ.РФ реестр ДДУ по ЖК — 100% на уровне агрегата. 3) Delta-tracking listings ЦИАН/Авито — 70% точность. 4) ДомКлик ипотечная статистика — sanity check на уровне района. 5) Фиксация снижений цен — сигнал «не продаётся»","Шахматки = золотая жила. На сайтах ПИК/Брусника/Атомстройкомплекс/ТЭН-Девелопмент/Стройтэк/ЛСР и др. интерактивная шахматка с поквартирным статусом (доступно/бронь/продано). Даёт площадь, комнатность, этаж, секцию, цену, дату продажи","Тех-план: воркер services/site_finder/sales_tracker.py + поадаптеру на каждого застройщика (brusnika_scraper.py, atomstroy_scraper.py...). Cron 1×в сутки. SPA-сайты — Playwright. SSR — httpx+BS4","Схема БД: apartments(id, jk_id, room_count, area_sqm, floor, section, price_rub, status, last_seen_at) + sales_history(apartment_id, sold_date, sold_price). Materialized views для velocity в радиусе X от точки","Три киллер-фичи из этих данных: A) Velocity Score в Site Finder — дополнительный 4-й критерий скоринга (сколько квартир продаётся/мес в радиусе 1км). B) Smart Unit-Mix в Generative — рекомендация долей 1/2/3-комн на основе реальных продаж в районе. C) Validation финмодели — бенчмарк прогноза выручки против факта по соседним ЖК","Это самый важный data moat: TestFit без РФ-данных, rTIM без site-selection и аналитики спроса. Через 6-12 мес накопления — уникальный источник данных для девелоперов, который не воспроизвести конкурентам быстро","План Discovery: Stage 2a нед.8-9 добавляется воркер sales_tracker параллельно парсеру ПКК. Реализуем 5-7 адаптеров (топ-застройщики Екбурга). К концу месяца 3 имеем 2-3 недели исторических данных","Целевые застройщики Екбурга для Discovery: Атомстройкомплекс, Брусника, ТЭН-Девелопмент, Стройтэк, Прогресс, УГМК-Застройщик, Кортрос, ЛСР-Урал, Forum-group, ПИК (если есть в ЕКБ)","Юридика: шахматки = публичные маркетинговые данные (без авторизации, серая зона мягче ЦИАН). Прецедентов исков застройщиков к парсерам практически нет (им нужны шахматки как воронка маркетинга). Для реестра ПО декларируем как «партнёрские интеграции с открытыми источниками застройщиков»","Анти-риски: 1) Сайт застройщика меняет вёрстку — скрейпер ломается, нужен Sentry alerting. 2) Юр-претензия от крупного застройщика — митигация через «партнёрство возамен аналитики» с топ-3 таргетов. 3) Низкое качество сайтов мелких застройщиков — берём только тех, у кого нормальный веб-интерфейс","Через 6 мес накопления: сезонные коэффициенты, absorption curves по типам квартир, ML-предсказание velocity для нового участка. Для Раунда А это идеальный narrative: «уникальная база продаж новостроек Свердловской обл., которой нет в открытых источниках и у западных игроков»"]} +{"type":"entity","name":"PlanA_AnalyticsFirst_Apr25","entityType":"decision_pending","observations":["Дата: 25 апреля 2026, вечер. Обсуждали с Антоном (второй разработчик)","Новые вводные: Антон сказал, что есть доступ ко всем сделкам для анализа. Детали по данным будут в понедельник 27 апреля 2026","Предложение Антона: сначала аналитика по продажам (что строить, какие квартиры, площади), потом всё остальное","Решение (предварительное, ждём детали): НЕ полный pivot. Перестановка порядка этапов: Stage 1 = Sales Analytics (нед 2-5), Stage 2 = Generative со Smart Defaults из аналитики (нед 6-10), Stage 3 = Site Finder с Velocity Score (нед 11-12)","Обоснование не полного pivot: Generative — главный дифференциатор против rTIM/TestFit. Без него конкурируем напрямую с ЕРЗ/ДОМ.РФ (у них 5 лет данных и команда). Аналитика становится мозгом для Generative и Site Finder, а не их заменой","Концепция «3 плитки»: ввод участок + класс жилья → (1) ЧТО СТРОИТЬ (unit-mix с velocity), (2) СКОЛЬКО ПРОСИТЬ (распределение цен м² по классам + тренд), (3) ЗА КАКОЕ ВРЕМЯ ПРОДАСТСЯ (absorption curves по АНАЛОГам). Кнопка «Сгенерировать концепцию» ведёт в Generative","Плюс нового плана: продаваемый артефакт уже после мес 1 (раньше был конец мес 2). Меньше технического риска. Другой ICP (инвестдепартамент вместо архитектуры)","КРИТИЧНО: «доступ ко всем сделкам» — это фундамент или мина. Бывают 4 сценария: 1) Легальный богатый ongoing (ЕРЗ Premium/банк/админ) → полный pivot, аналитика фундамент. 2) Легальный ограниченный → план A + шахматки параллельно для ongoing. 3) Серый канал → НЕ строим бизнес на этом, используем только «для себя». 4) Обещают но не дают → идём по плану шахматок, ждём","6 блоков вопросов к Антону на 27 апреля: Природа канала (что именно за доступ); Поля данных (цена/метраж/комнатность/покупатель?); Покрытие (регионы/история); Свежесть (разовая выгрузка или ongoing); Условия использования в коммерческом продукте; Цена доступа","Что делаем до пн (не останавливаемся, но с осторожностью): SSH-ключ, выбор хостинга (Beget/Timeweb), Stage 0 скелет уже сделан. НЕ начинаем Shapely геометрию или парсер ПКК — приоритет может сместиться","Шахматки застройщиков НЕ отменяются даже если данные Антона полные: 1) Сделки в Росреестре регистрируются с лагом 1-3 месяца. 2) Бронирования и доступность — сделки этого не показывают. 3) Маркетинговая цена vs фактическая различается","Сообщили Кене ответ Антону: направление в точку, но не полный pivot. Ждём детали по данным в пн. Вижу 6 блоков вопросов. От ответов зависит тип плана","Уточнение 25.04.2026 вечер: Антон подтвердил — речь идёт о ДДУ (Договорах Долевого Участия). Это идеальный источник для аналитики: ground truth по продажам новостроек, выше качеством чем шахматки","ДДУ поля стандартно: кадастровый номер квартиры, площадь, цена, дата регистрации, застройщик, ЖК. иногда комнатность/этаж/секция. ПН-поверхность: ПДн покупателя часто включены — обязательное обезличивание до записи в нашу БД (152-ФЗ)","Лаг ДДУ: 30-90 дней от реальной сделки до регистрации в Росреестре. Поэтому шахматки застройщиков НЕ отменяются — они дают 'today snapshot', ДДУ дают 'historical truth'","5 блоков к понедельнику (сужены до ДДУ-специфики): 1) Канал — держатель и договор (DOM.RF API/ЕРЗ Premium/банк/администрация/другое). 2) Поля (все ли обязательные + комнатность и ПДн). 3) Покрытие (регионы/история). 4) Свежесть (разовая/ongoing/real-time и лаг). 5) Условия коммерческого использования","Преимущество ДДУ над шахматками: ground truth по фактической цене (не маркетинговой), историческая глубина, юридически чистый источник (если канал легален), data moat относительно TestFit/rTIM"]} +{"type":"entity","name":"Runbook_VPS_Setup_Beget","entityType":"runbook","observations":["Источник: фактическая настройка сервера Jolly Yakov в Beget Cloud, 25.04.2026. Сервер 2 vCPU / 4GB RAM / 40GB NVMe / Ubuntu 24.04, IP 46.173.16.127","ШАГ 1: Создание сервера в cp.beget.com/cloud → Создать сервис → VPS → Standard 3+ GHz → 2 ядра/4GB/40GB. ОС: Ubuntu 24.04. Включить публичный IPv4. После создания сервер получает IP, root пароль выслан на email","ШАГ 2: Генерация SSH-ключа локально (если ещё нет). Windows PowerShell: ssh-keygen -t ed25519 -C 'gendesign-deploy' -f $HOME\\.ssh\\gendesign_deploy. Пароль оставить пустым (Enter Enter) — нужно для автодеплоя","ШАГ 3: Добавление публичного ключа на сервер через панель Beget. При проблемах со SSH (Connection reset, fail2ban) — войти через VNC терминал в браузере и добавить в ~/.ssh/authorized_keys","ШАГ 4: Первый вход по SSH с явным ключом. Команда: ssh -i $HOME\\.ssh\\gendesign_deploy root@. При первом коннекте спросит fingerprint — yes","ШАГ 5: На сервере (root): обновить пакеты 'apt update && apt upgrade -y'. Если [-f /var/run/reboot-required] то ребут. Установить hostname/timezone: hostnamectl set-hostname gendesign; timedatectl set-timezone Europe/Moscow","ШАГ 6: Создание non-root пользователя. adduser gendesign (задать сильный пароль, остальное Enter). usermod -aG sudo gendesign. Копия SSH-ключа root→gendesign: mkdir -p /home/gendesign/.ssh && cp ~/.ssh/authorized_keys /home/gendesign/.ssh/ && chown -R gendesign:gendesign /home/gendesign/.ssh && chmod 700 /home/gendesign/.ssh && chmod 600 /home/gendesign/.ssh/authorized_keys","ШАГ 7: Тест первого входа как gendesign. Важно: хранить root-сессию открытой как safety net до конца. В новом окне: ssh -i $HOME\\.ssh\\gendesign_deploy gendesign@. Проверка sudo: sudo whoami → root","ШАГ 8 (Windows-специфика): SSH config не создавать через Notepad — он добавляет .txt и сохраняет в UTF-8 с BOM. Правильный способ: PowerShell heredoc | Out-File -Encoding ascii -FilePath $HOME\\.ssh\\config. Блок Host: HostName , User gendesign, Port 22, IdentityFile ~/.ssh/gendesign_deploy, IdentitiesOnly yes, ServerAliveInterval 60. Критично включать IdentitiesOnly yes — иначе Windows OpenSSH перебирает все ключи и получает MaxAuthTries reset не дойдя до нужного","ШАГ 9: Отключение root-логина и паролей в SSH. ТОЛЬКО ПОСЛЕ подтверждения gendesign работает и sudo работает. sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak; sudo nano /etc/ssh/sshd_config → PermitRootLogin no, PasswordAuthentication no, PubkeyAuthentication yes. sudo sshd -t для валидации. sudo systemctl reload ssh","ШАГ 10: Критический тест в третьем окне: ssh gendesign → пускает по ключу. В четвёртом: ssh root@ → должен отказать. Старую root-сессию закрываем только после этого","Распространённые грабли: 1) Connection reset при неверном пароле = fail2ban Beget. Обход через VNC. 2) Notepad вместо config пишет config.txt — проверять ls $HOME\\.ssh\\. 3) Windows OpenSSH без IdentitiesOnly перебирает все ключи. 4) Группа sudo не подхватывается без выхода-входа. 5) При UNPROTECTED PRIVATE KEY FILE использовать icacls /inheritance:r /grant:r '<имя>:(R)'","Статус 25.04.2026 вечер: Шаги 1-7+8 выполнены. gendesign@46.173.16.127 работает по ключу, sudo работает. Осталось: SSH hardening (Шаг 9), UFW firewall, установка Docker, клонирование репо в /opt/gendesign","Статус 25.04.2026 вечер (обновлён): Базовая настройка VPS завершена. gendesign@46.173.16.127 работает по ключу, sudo работает. UFW активен (22/80/443). SSH hardening: PermitRootLogin no, PasswordAuthentication no, PubkeyAuthentication yes через drop-in /etc/ssh/sshd_config.d/00-gendesign-hardening.conf (приоритет 00- перебивает cloud-init defaults). Docker и git установлены. Репо клонировано в /opt/gendesign через deploy key github_deploy. PostgreSQL+PostGIS и Redis работают в докер-компоуз. PostGIS_Version() = 3.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1","Осталось: GHCR setup (замена YCR на GHCR в deploy.yml + docker-compose.prod.yml), GitHub Secrets, Caddy reverse proxy, домен, первый автодеплой backend+frontend","ВЕХА 25.04.2026 вечер: Первый успешный автодеплой. GitHub Actions воркфлоу deploy.yml прошёл полный цикл: build обоих образов (backend ~2.5мин, frontend ~1мин) → push в GHCR (ghcr.io/lekss361/gendesign-backend, gendesign-frontend, приватные) → SSH на сервер → docker compose pull (с PAT-авторизацией) → up -d. /health отвечает {status:ok, environment:prod}","GHCR пакеты остаются ПРИВАТНЫМИ (решение пользователя для защиты алгоритмов). Сервер авторизуется в GHCR через PAT с read:packages, сохранён в ~/.docker/config.json. PAT с длительным сроком или без срока","Исправлены во время деплоя: backend Dockerfile (убрал невалидный conditional COPY для alembic, перешли на uv sync без --frozen до генерации lockfile); frontend package.json (react-leaflet 4→5 для совместимости с React 19); frontend Dockerfile (npm install --legacy-peer-deps вместо npm ci, пока нет lockfile); frontend/public/.gitkeep для Next.js standalone build","Статус инфраструктуры к 25.04.2026 19:00: VPS Beget работает (Москва, 2/4/40 NVMe). UFW + SSH hardening + non-root user. Docker compose prod поднят с 5 сервисами (postgres+redis+backend+frontend+caddy). GitHub Actions автодеплой работает на push в main. /health публичен внутри VM (127.0.0.1:8000)","Осталось до «infra-ready»: домен, Caddy TLS с Let's Encrypt на этот домен, регулярные pg_dump в Object Storage, frontend NEXT_PUBLIC_API_BASE_URL на реальный домен (сейчас пустая). И дальше — Stage 1 разработки по выбранному PlanA_AnalyticsFirst_Apr25 (после понедельника с Антоном по ДДУ-данным)"]} {"type":"relation","from":"Project_GenDesign","to":"TechStack_v2.2","relationType":"uses"} {"type":"relation","from":"Project_GenDesign","to":"NorthStar_DiscoveryMVP","relationType":"targets"} {"type":"relation","from":"Project_GenDesign","to":"Phase0_DiscoveryMVP","relationType":"currently_executes"} {"type":"relation","from":"Phase0_DiscoveryMVP","to":"NorthStar_DiscoveryMVP","relationType":"delivers"} {"type":"relation","from":"Validation_Findings_Apr25","to":"Project_GenDesign","relationType":"reviews"} {"type":"relation","from":"Validation_Findings_Apr25","to":"TechStack_v2.2","relationType":"validates"} -{"type":"relation","from":"MemoryAutoSync_macOS_Apr25","to":"Project_GenDesign","relationType":"supports"} -{"type":"relation","from":"MemoryAutoSync_macOS_Apr25","to":"Feedback_MemoryFirst","relationType":"implements"} -{"type":"relation","from":"Phase0_DiscoveryMVP","to":"MVP_Scope_AreaSelect_Apr25","relationType":"includes"} -{"type":"relation","from":"MVP_Scope_AreaSelect_Apr25","to":"Project_GenDesign","relationType":"refines"} -{"type":"relation","from":"MVP_Scope_AreaSelect_Apr25","to":"NorthStar_DiscoveryMVP","relationType":"informs"} \ No newline at end of file +{"type":"relation","from":"SalesTracking_Strategy_Apr25","to":"Project_GenDesign","relationType":"strengthens"} +{"type":"relation","from":"SalesTracking_Strategy_Apr25","to":"DataSources_Pricing_Apr25","relationType":"extends"} +{"type":"relation","from":"SalesTracking_Strategy_Apr25","to":"Phase0_DiscoveryMVP","relationType":"modifies"} +{"type":"relation","from":"SalesTracking_Strategy_Apr25","to":"Stages_MVP_v1","relationType":"amends_stage_2a"} +{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"Stages_MVP_v1","relationType":"supersedes"} +{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"WorkSplit_Generative_Stage1","relationType":"needs_revision"} +{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"SalesTracking_Strategy_Apr25","relationType":"depends_on"} +{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"DataSources_Pricing_Apr25","relationType":"depends_on"} +{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"Project_GenDesign","relationType":"reshapes"} \ No newline at end of file