gendesign/README.md
lekss361 522ecca5c4 ship #13-16: multi-target Dockerfile, per-object drill-in, CRM pipeline,
442-sweep instructions
#16 Dockerfile: runner (lean, 1.6 GB) + runner-with-chromium (2.9 GB).
   Compose + deploy.yml pushes 2 GHCR images. Backend saves 1.3 GB.
#15 5 backend object endpoints + /analytics/objects/[id] page (gallery,
   POI table, sale chart) + sparkline-driven PrinzipObjectsTable.
#14 prinzip_leads/deals + 2 MVs. Import script with PII-hashing &
   --inspect-only mode. 3 funnel endpoints + Sankey/Monthly charts.
#13 README section with UI/CLI/SQL for 442-object sweep.
2026-04-27 19:32:37 +03:00

724 lines
54 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Generative Design + Site Finder
Две продуктовые линии в одной воронке: **Site Finder** (AI-подбор инвестиционных земельных участков) + **Generative Design** (автоматическая генерация концепций застройки) для девелоперов РФ.
## North Star
К концу месяца 3: **3 платящих пилота** (≥30 тыс. ₽/мес каждый) + заявка в реестр российского ПО → право на Раунд А (2025 млн ₽).
Acceptance criteria разбиты на 3 блока (функционально / бизнесово / технически). Правило перехода: 3/3 → Раунд А; 2/3 → продление Фазы 0 на 12 мес.; 1/3 или меньше → стоп проекта.
---
## Текущий статус (27 апреля 2026)
**Инфраструктура: live на HTTPS.** Прод доступен по [https://gendsgn.ru/](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/](https://gendsgn.ru/) | ✅ HTTP/2 + HTTP/3, валидный TLS |
| **Health endpoint** | [https://gendsgn.ru/health](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` в графе памяти.
**26.04 вечер — data discovery разблокировал Plan A независимо от Антона.** Найдены три легальных канала ground-truth-данных:
1. **Росреестр CSV-датасет** (`DataSource_Rosreestr_DealsCSV_Apr26`) — per-deal цены сделок ДКП+ДДУ из ФГИС ЕГРН, 9 кварталов 2024Q1 2026, ~898К сделок РФ/квартал. Открытые данные по 8-ФЗ, разделитель `~`, гранулярность до кадастрового квартала.
2. **ДОМ.РФ фронт-API** (`DataSources_Analysis_Apr26` + 12 вкладок) — открытые JSON без auth (либо `Basic MTpqd2U=` хардкоден), per-flat прайс-лист, реализация/готовность как velocity.
3. **НСПД MarketAnalytics** (`NSPD_MarketAnalytics_FullArchitecture_Apr26`) — индикаторы цен по кадастровым кварталам, 8 лет longitudinal, GeoJSON-полигоны для heatmap. Архитектура полностью раскрыта в debug-браузере (saveUserFilters → graphEgrn*/tableEgrn/geomDataForHeatMap, серверная сессия фильтров через userFiltersId). ⚠ `graphEgrnCandleMedian`/`LineMedian` (абсолютные ₽/м²) дают 403 для physic-аккаунта — но эти данные мы уже получаем из CSV-датасета Росреестра.
**27.04 — analytical layer полностью построен.** В прод-БД 43 `domrf_*/cbr_*/yandex_*/ekb_*/sv_*/rosreestr_*` таблицы (см. блок «Аналитический пласт данных» ниже). За день:
- Загружено 5 lazy-load страниц ДОМ.РФ (`DomRF_Lazy_Loaded_Apr27_2026`) — `domrf_realization` 9.7K + stat_series XLSX 809K observations + 333 raw JSONB endpoints.
- Догружена история 14 месяцев (Янв 2025 - Февр 2026) для realization + sold_ready через `repYear/repMonth` параметры (`DomRF_History_Loaded_Apr27_2026`) — `domrf_realization` итого **143 963** рядов, sold_ready_breakdown расширен до 7 chart-types с типизированными колонками.
- Импортирован SQLite Антона (23 МБ) — 13 новых таблиц: `domrf_kn_flats` (27 563 поквартирно), `domrf_kn_objects` (1 516 ЖК), `cbr_mortgage_series` (3 308 ЦБ), `sber_ddf_metrics`, `yandex_realty_zk`, `ekb_districts`, `rosreestr_rent_deals`. Архив девелоперов смерджен (2 734 → 8 629). См. `Anton_Imported_Apr27_2026`.
- Подключён MCP `crystaldba/postgres-mcp` (`.mcp.json`) — все DDL/SELECT теперь через `mcp__postgres__execute_sql` без `docker run psql` обёртки.
- FK-аудит и cleanup: добавлены 4 missing FK, дропнуты 2 дублирующих индекса и 2 устаревшие таблицы (`sold_out_by_year`, `sold_out_by_progress``domrf_realization`), 8 `COMMENT ON TABLE` для документации источников.
- Territory aliases для stat_series ↔ regions name mapping (`v_stat_series_resolved` view): 100% покрытие 809K observations через 101 alias.
- Готовы 2 стратегических отчёта: `Sverdl_Quartirography_Report_Apr27` (общий по Свердл) + `PRINZIP_Strategy_Apr27` (что строить и куда смотреть).
**27.04 вечер — analytics dashboard + DOM.РФ scraper.** Поверх аналитического пласта собран интерактивный дашборд + регулярный парсер для пополнения данных:
- **Веб-аналитика** (`Analytics_Dashboard_Apr27`) — 3 страницы на ECharts/React Query: `/analytics` (рынок Свердл — KPI + market-pulse + парадокс «строят vs покупают» + pipeline + treemap районов ЕКБ), `/analytics/prinzip` (drill-down PRINZIP с benchmark-velocity, gap-bar к рынку, инсайты из стратегии), `/analytics/developers` (топ-15 + scatter velocity). Backend: `/api/v1/analytics` 11 endpoints поверх `v_developer_full_metrics`.
- **DOM.РФ kn-API парсер** (`DomRf_Kn_Scraper_Apr27`) — Playwright in-context fetch (httpx бьётся об ServicePipe TLS-fingerprint, проверено), правильные endpoints `/сервисы/api/kn/object` (place=66, objStatus 0/1/2 = 442+2+1072 = **1516 ЖК Свердл, точно совпало с БД**) + `/portal-kn/api/sales/portal/table` (квартиры). Auth — `Basic MTpqd2U=` (`1:qwe`, не `jwe`!). Серверная фильтрация по `regions/developers` НЕ работает — фильтруем локально по `developer.companyGroup`.
- **Extras-эндпойнты** (per-ЖК, того же sweep): `/sale_graph?type=apartments|parking` (time-series продаж), `/sales_agg` (текущие агрегаты 3 типов), `/infrastructure` (POI), `/construction/progress/photo` (мета+опц. binary). PRINZIP probe: 28 ЖК → 36 sale_graph + 6 sales_agg + 5 409 POI + 5 150 фото-метаданных.
- **Расписание + ручной триггер** — Celery beat (cron из `SCRAPE_KN_CRON` env, jitter 0..30мин), `POST /api/v1/admin/scrape/kn` с `X-Admin-Token`, UI `/admin/scrape` (чекбоксы extras/photos + журнал ошибок с copy-URL для ручной проверки в браузере + раздел «Очередь и активные» через Celery inspect).
- **Stealth** — Playwright fingerprint снят с локальной машины в `data/playwright_state.json` (26 cookies, ServicePipe NSC + Keycloak), закоммичен в git для server-reuse без cold-bootstrap.
### Запуск 442-sweep (все строящиеся ЖК Свердл)
После того как PRINZIP-probe прошёл (28 ЖК), масштабируем на все 442 строящихся:
**Через UI** (рекомендуется):
1. Открыть https://gendsgn.ru/admin/scrape, ввести `SCRAPE_ADMIN_TOKEN`.
2. Регион: 66, Девелоперы: пусто (все), чекбоксы: ✅ Квартиры, ✅ Extras, ❌ Скачать фото.
3. «Запустить сейчас» → таск уйдёт в Redis-очередь, worker подхватит. Прогон ~60 минут.
**Через CLI на VPS** (если worker оффлайн):
```bash
ssh gendesign 'cd /opt/gendesign && \
docker compose -f docker-compose.prod.yml run --rm worker \
python data/sql/50_scrape_kn_flats.py --regions 66 \
--load-state data/playwright_state.json -v'
```
**Sanity-чеки после прогона:**
```sql
SELECT obj_status, COUNT(*) FROM domrf_kn_objects
WHERE region_cd=66 AND snapshot_date=CURRENT_DATE GROUP BY 1;
-- Ожидаем obj_status=0 (строящиеся): ~442
SELECT COUNT(DISTINCT obj_id) FROM domrf_kn_sale_graph
WHERE snapshot_date=CURRENT_DATE;
-- Ожидаем 100-200 ЖК с активными продажами
SELECT poi_category, COUNT(*) FROM domrf_kn_infrastructure
WHERE snapshot_date=CURRENT_DATE GROUP BY 1 ORDER BY 2 DESC;
-- Ожидаем ~85 000 POI (442 ЖК × ~190 POI на ЖК)
```
**Возможные проблемы:**
- WAF cookie expire — обновить `data/playwright_state.json` через `python data/sql/50_scrape_kn_flats.py --regions 66 --bootstrap-only --save-state data/playwright_state.json` локально, закоммитить, redeploy.
- Rate-limit (429) — повысить `SCRAPE_KN_JITTER_SECONDS` в env или поправить `jitter_sleep(min_ms, max_ms)` в `stealth.py`.
---
## Аналитический пласт данных (data warehouse) — 27.04.2026
В прод-БД `gendesign` живёт **43 предметных таблицы** + 5 helper views + Rosreestr partitions. Размер БД ~2.1 ГБ.
### 🔌 Подключение
| Метод | Команда |
|---|---|
| **MCP** (рекомендуется) | конфиг в `.mcp.json` (project root) — `mcp__postgres__execute_sql`, `analyze_db_health`, `list_objects`, `explain_query` и т.д. |
| **psql via SSH-туннель** | `ssh -fN -L 15432:127.0.0.1:5432 gendesign` затем `PGPASSWORD=… psql -h 127.0.0.1 -p 15432 -U gendesign gendesign` |
| **DBeaver / TablePlus** | localhost:15432 после открытия SSH-туннеля |
⚠️ Туннель уже открыт на машинах команды (gendesign@46.173.16.127). `.mcp.json` в `.gitignore` (содержит пароль).
### 📊 Карта таблиц (43 предметных)
**ROSREESTR per-deal (1.1 ГБ)**
| Таблица | Рядов | Описание |
|---|---:|---|
| `rosreestr_deals` (+ 7 партиций по кварталам 2024Q3-2026Q1) | 4 975 398 | Сырые сделки ДКП+ДДУ из ФГИС ЕГРН, 89 регионов |
| `rosreestr_deals_staging` | UNLOGGED | буфер для `\copy` из CSV |
| `rosreestr_rent_deals` | 1 071 | Договоры аренды Свердл Q1 2026 (Антон) |
**ROSREESTR materialized views (305 МБ)**
| MV | Рядов | Описание |
|---|---:|---|
| `rr_agg_cad_quarter` | 952 799 | (region, cad_quarter, period, doc_type, area_bucket) → p10/median/p90 ₽/м² |
| `rr_agg_settlement` | 422 852 | (region, settlement, period, doc_type, realestate_type) |
| `rr_agg_region` | 3 549 | percentile-агрегаты по регионам |
**DOM.РФ справочники / dimensions**
| Таблица | Рядов | Описание |
|---|---:|---|
| `domrf_regions` | 90 | PK region_id (0=РФ + 89 субъектов). FK target для 4 таблиц |
| `domrf_developers` | **8 629** | реестр + архив (после merge с Антоном). PK developer_id ('6208_0'=PRINZIP) |
| `domrf_developers_full` | 2 563 | XLSX-выгрузка с метриками area/permits/flats/share |
| `domrf_snapshots` | 18 | snapshot_date dimension (4 базовых + 14 history Янв 2025-Февр 2026) |
| `domrf_federal_districts` | 8 | 8 ФО как first-class lookup |
| `domrf_territory_aliases` | 101 | text→(level, region_id\|fo_id) для нормализации имён |
| `domrf_stat_series_indicators` | 123 | XLSX sheet codes → indicator_name |
**DOM.РФ realization & sold_ready (history)**
| Таблица | Рядов | Описание |
|---|---:|---|
| `domrf_realization` | **143 963** | 4 endpoint_types (total/housing/ready_year/developer) × 89 регионов × 14 monthly snapshots |
| `domrf_sold_ready_index` | 15 | РФ-итог helio метрики per snapshot |
| `domrf_sold_ready_breakdown` | 40 044 | 7 chart_types × dim_value × 14 snapshots (regionChart/devChart/foChart/cityPopulationChart/classChart/devValueChart/readyYearChart) с типизированными колонками |
| `domrf_sold_ready_dynamics` | 3 450 | timeseries 2020-period × 4 chart_types |
**DOM.РФ JSON dashboard**
| Таблица | Рядов | Описание |
|---|---:|---|
| `domrf_region_aggregates` | 439 | (region, room_count_type) → flat_count/area/percent |
| `domrf_developer_aggregates` | 11 063 | (developer × region × room_count) |
| `domrf_flat_area_distribution` | 40 | РФ-уровень бакеты площади |
**DOM.РФ XLSX/PDF снапшоты**
| Таблица | Рядов | Описание |
|---|---:|---|
| `domrf_developers_full` | 2 563 | реестр девелоперов из XLSX |
| `domrf_escrow_banks` | 28 | банки эскроу (Сбер 61%) |
| `domrf_guaranty_regions` | 99 | РФ + 8 ФО + 89 регионов разбивка |
| `domrf_housing_summary` | 58 | разбивка по механизмам |
| `domrf_planned_commissioning` | 10 | план ввода 2026-2035 |
| `domrf_sold_out` | 9 | РФ + 8 топ-регионов (PDF, ради unique `attracted_funds_mln_rub`) |
| `domrf_mortgage_rates` | 20 | ставки топ-20 банков (PDF) |
**DOM.РФ launch / commissioning**
| Таблица | Рядов | Описание |
|---|---:|---|
| `domrf_launch_top` | 1 410 | топ-N developer/region/area/fo по запускам/вводу |
| `domrf_launch_obj_class` | 4 | Типовой/Комфорт/Бизнес/Элитный |
| `domrf_launch_monthly` | 75 | timeseries 2020-2026 |
| `domrf_commissioning` | 1 | факт ввод (multifamily/private) |
| `domrf_project_finance` | 99 | ПР финансирование РФ/ФО/регионы |
**DOM.РФ stat_series (parsed XLSX 254 МБ)**
| Таблица | Рядов | Описание |
|---|---:|---|
| `domrf_stat_series_observations` | **809 236** | long-form panel: 99 территорий × 123 индикатора × ~70 месяцев (2020-2026) |
| `domrf_xlsx_files` | 9 | BYTEA-архив исходных XLSX (8 МБ) |
**DOM.РФ ipoteka / mortgage**
| Таблица | Рядов | Описание |
|---|---:|---|
| `domrf_mortgage_dashboard` | 1 | агрегат рынка ипотеки РФ |
| `domrf_mortgage_details` | 2 | RUB/OTH валюты |
**DOM.РФ /сервисы/api/kn/* (от Антона + наш scraper)**
| Таблица | Рядов | Описание |
|---|---:|---|
| `domrf_kn_flats` | 28 389+ | поквартирный прайс. Антоновский snapshot 2026-04-27 + наши новые snapshot'ы (UNIQUE по `(id, snapshot_date)`) |
| `domrf_kn_objects` | 1 516+ | реестр ЖК Свердл (1285 ЕКБ + 28 PRINZIP) с GPS, классом, эскроу. Наш scraper подтвердил 442+2+1072=1516 для региона 66 |
| `domrf_dev_growth` | 139 | динамика 2024→2025 девелоперов |
| `domrf_kn_sale_graph` ⭐ | 36+ | time-series продаж per-ЖК (apartments/parking × месяц). PRINZIP Парк Победы продал 95 квартир в 2025 |
| `domrf_kn_sales_agg` ⭐ | 6+ | текущие агрегаты per-ЖК (apartments/nonliv/parking × total/realised/perc). Парк Победы 145/291=49% |
| `domrf_kn_infrastructure` ⭐ | 5 409 | нормализованная POI вокруг ЖК (Спорт, Продукты, Образование, Медицина, Развлечения) с lat/lon/dist_m |
| `domrf_kn_photos` ⭐ | 5 150 | метаданные фото прогресса стройки (URL + period_dt + size_bytes), binary в `data/raw/domrf_photos/` опционально |
| `kn_scrape_runs` | 3 | журнал прогонов парсера: regions, developers, objects_count, flats_count, requests_count, status |
| `kn_scrape_failures` | 78 | per-request ошибки с full_url для ручной проверки в браузере (404 для сданных ЖК = ожидаемо) |
**PRINZIP CRM (analytics.prinzipevent.ru)**
| Таблица | Рядов | Описание |
|---|---:|---|
| `prinzip_leads` ⭐ | до 102 000 | заявки 8 лет. PII (phone/email) хешированы. Импорт через `data/sql/52_import_prinzip_crm.py --sqlite data/raw/prinzip_crm.sqlite` |
| `prinzip_deals` ⭐ | до 9 000 | сделки 8 лет, sum revenue ≈ 39.9 млрд ₽. FK к `prinzip_leads` и soft-FK к `domrf_kn_objects` |
| `prinzip_funnel_monthly` ⭐ | MV | воронка по месяцам × source (REFRESH после импорта) |
| `prinzip_funnel_by_object` ⭐ | MV | conversion per ЖК: leads → deals → revenue |
**ЦБ РФ ипотека (от Антона)**
| Таблица | Рядов | Описание |
|---|---:|---|
| `cbr_mortgage_series` | 3 308 | 47 серий × {rf,sverdl} × Jan 2019 - Feb 2026 |
| `cbr_mortgage_files` | 19 | XLSX-источники |
**Внешние источники**
| Таблица | Рядов | Описание |
|---|---:|---|
| `sber_ddf_metrics` | 20 | Сбер ДомКлик DDF nov2025: affordability, demand index, миграция, повторные ипотечники, price gap |
| `yandex_realty_zk` | 12 | Yandex Realty ЖК ЕКБ snapshot |
| `yandex_realty_class_prices` | 3 | разбивка по классам econom/comfort/elite |
**Geo Свердл/ЕКБ**
| Таблица | Рядов | Описание |
|---|---:|---|
| `ekb_districts` | 9 | 9 районов ЕКБ с zk_count/flat_count/area |
| `ekb_metro` | 10 | станции метро ЕКБ |
| `sv_cities` | 24 | не-ЕКБ города Свердл (Н.Тагил, Первоуральск, Арамиль) |
| `sv_dev_sales` | 50 | ТОП-50 Свердл девелоперы Март 2026 |
**Universal raw**
| Таблица | Рядов | Описание |
|---|---:|---|
| `domrf_raw_endpoints` | 349 | universal JSONB store: каждый /api/* response с GIN-index на payload |
### 🔍 Helper views (9 шт)
**Базовые (legacy):**
| View | Описание |
|---|---|
| `v_market_pulse_rf` | one-row live-метрика РФ: 118.7M м² стройка / sold 30.91% / Цена 216 316 ₽/м² / ставка 19.9% vs 6.83% |
| `v_developer_master` | полный профиль девелопера (legacy). PRINZIP sold% 48.4% — ЛИДЕР Свердл |
| `v_region_master` | one-row-per-region: квартирография + sold_out + sold_ready + project_finance + guaranty + launch |
| `v_rosreestr_market_by_region` | Rosreestr p10/median/p90 + DOM.РФ имена |
| `v_stat_series_resolved` | stat_series_observations + alias + indicator_name (`WHERE region_id=66` → Свердл) |
**Связи квартиры↔ЖК↔застройщики (NEW 27.04 evening):**
| View | Описание |
|---|---|
| `v_jk_with_developer` | ЖК Свердл + canonical dev_name + region_name (через FK `fk_kn_obj_developer/region`). 1 516 строк. |
| `v_jk_sales_summary` | flats GROUP BY obj_name: total/sold/booked/free + sold_pct + avg_ppm + avg_area + total_value. Standalone-вид поквартирных снапшотов из `domrf_kn_flats`. |
| `v_developer_portfolio` | Девелопер + все его корпуса/ЖК Свердл: count, flats_total, sqm + фильтры ekb/problem/escrow/completed/in_progress + earliest/latest ready_dt. |
| `v_developer_full_metrics` | **⭐ ULTIMATE QUERY**: portfolio (ЖК) + квартирография (1к/2к/3к/4+) с процентами + realization Свердл sold%/цена. Лучший view для PRINZIP/Брусника/конкурентов сравнения. |
### 🔗 FK relationships
**35 FK constraints** (после relations v2):
- `domrf_snapshots`: 24 child FKs (все таблицы со snapshot_date)
- `domrf_regions`: 5 (developer_aggregates, flat_area_distribution, region_aggregates, realization, kn_objects⭐, rent_deals⭐, territory_aliases)
- `domrf_developers`: 3 (developer_aggregates, **kn_objects** ⭐ NEW, **sv_dev_sales** ⭐ NEW)
- `domrf_federal_districts`: 1 (territory_aliases)
**Цепочка анализа продаж:**
```
domrf_kn_flats (поквартирно) ─── obj_name ──→ domrf_kn_objects (ЖК)
│ dev_id (FK)
domrf_developers (справочник)
│ developer_id (FK)
domrf_realization (sold%/price 14 мес)
│ region_code=66 ─→ domrf_regions
```
**Известное ограничение**: `domrf_kn_flats.obj_id` НЕ имеет FK на `domrf_kn_objects.obj_id` — два API endpoint используют разные ID-системы (27 563/27 563 orphans, текстовый match по `obj_name`/`comm_name` тоже даёт только 2 совпадения). Поквартирные снапшоты обрабатываются standalone через `v_jk_sales_summary`.
### 📜 ETL artefacts (data/sql/)
```
01_schema_rosreestr_deals.sql partitioned table + staging
02_load_all_quarters.sh \copy CSV (sep ~ и ;)
03_materialized_views.sql 3 MV для аналитики
10_schema_domrf.sql domrf_regions/developers/snapshots/aggregates
11_load_domrf.py JSON dashboard loader
20_schema_domrf_extras.sql XLSX/PDF schemas
21_load_domrf_extras.py XLSX/PDF loader
30_scrape_domrf.py Playwright headless Chromium с per-page direct API triggers
31_schema_domrf_full.sql launch/sold_ready/etc normalized
31_schema_domrf_raw.sql universal JSONB store
32_load_domrf_full.py normalize scraper output
32_load_domrf_raw.py JSONB raw store loader
33_schema_domrf_lazy.sql domrf_realization + xlsx_files (5 lazy pages)
34_load_domrf_lazy.py realization/xlsx/raw loader
35_schema_domrf_stats.sql stat_series_indicators + observations
36_parse_xlsx_stats.py parse 7 XLSX → 809K observations
37_cleanup_redundant.sql DROP sold_out_by_year/progress
38_relations_fix.sql +4 FK, миграция -1→0 RF, drop dup indexes, COMMENT'ы
39_territory_aliases.sql federal_districts + territory_aliases + v_stat_series_resolved
40_relations.sql оригинальные FK + 4 helper views (legacy)
40_scrape_history.py 14-month history scraper для realization+sold_ready
41_load_history.py loader с SNAPSHOT_DATE = end of period
42_schema_breakdown_widen.sql drop JSONB extra → 6 typed dimension columns
43_anton_import.sql 13 new tables for Anton's SQLite
44_import_anton_db.py sqlite3 → postgres migration
45_relations_v2.sql +4 FK (kn_obj→regions/developers, sv_dev_sales→developers, rent_deals→regions) + 4 analytical views (jk_with_developer, jk_sales_summary, developer_portfolio, developer_full_metrics)
50_schema_kn_extensions.sql UNIQUE (id, snapshot_date) для kn_flats/kn_objects + индексы (region_cd, snapshot_date) + kn_scrape_runs (журнал прогонов)
50_scrape_kn_flats.py CLI scraper для /сервисы/api/kn/object + portal/table; флаги --regions/--developers/--no-extras/--download-photos/--probe URL/--save-state/--load-state
51_schema_kn_extras.sql 4 extras-таблицы: sale_graph (time-series продаж), sales_agg (агрегаты), infrastructure (POI норм.), photos (мета+local_path) + kn_scrape_failures
52_schema_prinzip_crm.sql prinzip_leads (102K) + prinzip_deals (9K) + 2 materialized views (funnel_monthly, funnel_by_object). PII-hashing
52_import_prinzip_crm.py SQLite → Postgres importer. Use --inspect-only для discovery колонок, потом правь LEAD_FIELD_MAP/DEAL_FIELD_MAP
```
Парсер живёт в `backend/app/services/scrapers/{stealth.py, domrf_kn.py}`, Celery-таск в `backend/app/workers/tasks/scrape_kn.py`, admin endpoint в `backend/app/api/v1/admin_scrape.py` (POST /kn + GET /runs + GET /failures + GET /queue + POST /revoke с auth `X-Admin-Token`). UI ручного запуска: `frontend/src/app/admin/scrape/page.tsx`. Per-объект drill-in: `/analytics/objects/[id]` (галерея фото + POI-таблица + sale-chart) + `PrinzipObjectsTable` с sparkline на `/analytics/prinzip`.
### 🎯 Аналитика — что делать с этими данными
**Готовые отчёты в графе памяти:**
- `Sverdl_Quartirography_Report_Apr27` — полный отчёт по квартирографии Свердл (что строится, что продаётся, тренды 14 мес, топ-15 девелоперов)
- `PRINZIP_Strategy_Apr27` — стратегические рекомендации для PRINZIP (что строить, куда смотреть, BENCHMARK с Брусникой/Форум-групп)
**Использование (паттерны):**
```sql
-- Свердл realization timeseries за год
SELECT TO_CHAR(snapshot_date,'YYYY-MM') AS p, total_square, sold_perc, price_avg
FROM domrf_realization
WHERE region_code=66 AND endpoint_type='total' AND type_square='total'
ORDER BY snapshot_date;
-- ЕКБ ДДУ-сделки по площадным сегментам
SELECT
CASE WHEN area<30 THEN 'studio' WHEN area<45 THEN '1k' ... END,
COUNT(*), AVG(price_per_sqm)
FROM rosreestr_deals
WHERE region_code=66 AND city ILIKE '%катеринбург%'
AND period_start_date >= '2025-04-01' AND doc_type='ДДУ';
-- Свердл stat_series (МКД 214-ФЗ, временной ряд) через resolved view
SELECT obs_date, value
FROM v_stat_series_resolved
WHERE region_id=66 AND sheet_code='01_01_01';
-- Поквартирный прайс ЕКБ (Антон)
SELECT obj_name, rooms, total_area, price_per_m2, status
FROM domrf_kn_flats WHERE city='Город Екатеринбург' AND status='free';
-- Топ ЖК ЕКБ (Антон)
SELECT comm_name, dev_name, flat_count, square_living, ready_dt
FROM domrf_kn_objects WHERE is_ekb=true ORDER BY flat_count DESC;
```
---
## Структура репозитория
```
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 (нед. 27) ⏸ pending решения по Plan A
- **1a (нед. 23):** геометрия + API-контракт. Shapely-сервис (отступы, сетка), Pydantic-схемы, `POST /api/v1/concepts` с заглушкой. Фронт: страница `/concept`, Leaflet, импорт GeoJSON, форма параметров, 3 варианта в табах.
- **1b (нед. 45):** алгоритм размещения. Жадное заполнение, 3 стратегии (max площадь / max инсоляция / balanced), STRtree для коллизий. Цель ≤10 сек, fallback 15 сек.
- **1c (нед. 67):** ТЭП + финмодель + экспорты. WeasyPrint PDF, ezdxf, openpyxl. UI кнопок скачивания.
**Acceptance Stage 1 (конец нед. 7):** полигон → 3 варианта → ТЭП + финмодель → PDF/Excel/DXF.
### Stage 2 — Site Finder MVP (нед. 812)
- **2a (нед. 89):** data pipeline. Парсер ПКК Rosreestr (httpx async, retries), модель `Parcel` с GeoAlchemy2, ≥1000 участков Екатеринбурга. Overpass API для POI, ДОМ.РФ/ЦИАН для цен м², кеш в Redis. Опционально: воркер `sales_tracker.py` — ежесуточный мониторинг шахматок застройщиков (Velocity Score).
- **2b (нед. 1011):** скоринг + 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](https://docs.astral.sh/uv/) (для backend dev вне Docker).
```bash
# 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
```
**Полезное:**
```bash
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: ~1015 тыс ₽/мес.
### Что осталось до «infra-ready»
- [x] ~~Купить домен~~`gendsgn.ru` зарегистрирован в Beget 26.04.2026 (199₽/420₽). DNS на NS Beget, A-записи прописаны
- [x] ~~ЕСИА-верификация админа домена~~ — пройдено 26.04, статус `REGISTERED, DELEGATED, VERIFIED`
- [x] ~~Caddy TLS на `gendsgn.ru`~~ — Let's Encrypt cert получен, HTTPS живёт
- [x] ~~Sentry DSN~~ — проект `gendesign-backend` создан в org `qqq`, DSN в `/opt/gendesign/backend/.env`, тестовое событие прошло
- [x] ~~GitHub Issues / Milestones / Labels~~ — backlog засеян (см. [Issues](https://github.com/lekss361/-gendesign/issues))
- [ ] Настроить ежесуточный `pg_dump` → Object Storage. Скрипт `ops/backup.sh` готов, осталось создать Selectel/Yandex bucket и положить креды в `/etc/default/gendesign-backup` на VM ([#3](https://github.com/lekss361/-gendesign/issues/3))
- [ ] Прокинуть `SENTRY_RELEASE` в deploy.yml для tracking релизов в Sentry ([#4](https://github.com/lekss361/-gendesign/issues/4))
- [ ] Подключить Антона к knowledge-graph ([#11](https://github.com/lekss361/-gendesign/issues/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 backend`
- **`deploy.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. Всегда указывай `-f`
- **`caddy 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`:
1. **Build** обоих Docker-образов (backend ~2.5 мин с нуля, frontend ~1 мин с нуля; повторно из кеша — секунды)
2. **Push** в GHCR (`ghcr.io/lekss361/gendesign-backend`, `gendesign-frontend`) с тегами `latest` и `<sha7>`
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 раз в год.
---
## Память проекта (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` / `.pdf` Claude **не создаёт сам** — только по явному запросу
- Источник правды = граф, документы = производные срезы
**Рабочий цикл:**
```bash
git pull # перед началом работы
# ... сессия с Claude ...
git add memory/memory-gendesign.jsonl
git commit -m "Memory: <что добавили>"
git push
```
Конфликты в `.jsonl` обычно простые (файл построчный): `git pull --rebase`, оставить **обе** стороны, `git rebase --continue`.
### Подключение коллеги
Краткая инструкция для нового участника команды:
1. Установить Claude Desktop, Node.js 20+, Git
2. Клонировать репо в `C:\Users\<имя>\source\repos\gendesign`
3. `mkdir C:\mcp\.aim`
4. Создать хард-линк:
```powershell
New-Item -ItemType HardLink `
-Path C:\mcp\.aim\memory-gendesign.jsonl `
-Value $PWD\memory\memory-gendesign.jsonl
```
5. Добавить в `%APPDATA%\Claude\claude_desktop_config.json`:
```json
"knowledge-graph": {
"command": "npx",
"args": ["-y", "mcp-knowledge-graph", "--memory-path", "C:\\mcp\\.aim"]
}
```
6. Перезапустить Claude Desktop полностью (через трей)
7. Проверить: «Покажи память контекста gendesign»
Полная версия процедуры — в графе, сущность `Onboarding_Colleague_KG`.
---
## Документы стратегии
В `docs/`:
- `MVP_Goals_Python.md` — цели Discovery MVP, Python-стек (v2.2, апрель 2026)
- `Бизнес-план v2.1 - Site Finder + Roadmap 12 месяцев.md` — бизнес-план
⚠️ Эти документы — **снимок состояния на момент написания**. Свежее состояние стратегии — в графе памяти. При расхождении доверяем графу.
Релевантные сущности графа на 27.04.2026:
**Аналитика и отчёты (27.04):**
- `DomRF_Lazy_Loaded_Apr27_2026` ⭐ — итог дня: 5 lazy-load страниц + stat_series + cleanup + territory aliases + MCP
- `DomRF_History_Loaded_Apr27_2026` ⭐ — 14 месяцев истории realization+sold_ready (143K рядов realization)
- `Anton_Imported_Apr27_2026` ⭐ — 13 таблиц от Антона + merge developers (8 629 итого)
- `Sverdl_Quartirography_Report_Apr27` 📊 — полный отчёт по Свердл квартирографии
- `PRINZIP_Strategy_Apr27` 📊 — стратегия PRINZIP: что строить и куда смотреть
- `Analytics_Dashboard_Apr27` ⭐ — 3 страницы /analytics с ECharts (Свердл рынок, PRINZIP drill-down, девелоперы)
- `DomRf_Kn_Scraper_Apr27` ⭐ — парсер DOM.РФ kn-API + 4 extras-эндпойнта (sale_graph, sales_agg, infrastructure, photos), Playwright in-context fetch, Celery beat cron + admin trigger UI
Сущности 26.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 решение (ждём 27.04 — Антон по ДДУ)
- `SalesTracking_Strategy_Apr25` — шахматки застройщиков (downgrade-нуты после находок 26.04)
- `DataSources_Pricing_Apr25` — источники цен и площадей (общий обзор)
- `DataSources_Analysis_Apr26` — глубокий анализ ДОМ.РФ как ground truth (заменяет ожидание ДДУ-канала)
- `Validation_Findings_Apr25` — валидация бизнес-плана
**Источники данных (обновлено 26.04 вечер):**
- `DataSource_Rosreestr_DealsCSV_Apr26` ⭐ — per-deal цены сделок ДКП+ДДУ из ФГИС ЕГРН, 9 кварталов 2024Q1 2026, ~898К сделок РФ/квартал
- `DataSource_Rosreestr_DealsCSV_Schema_Apr26` — схема CSV (разделитель `~`, 17 полей)
- `DataSource_Rosreestr_DealsCSV_Sverdl_Q1_2026` — реальные цифры по Свердл.обл (ДКП median 82,594 ₽/м², ДДУ median 156,314 ₽/м²)
- `DataSource_Rosreestr_DealsCSV_Limits_Apr26` — ограничения (нет покупателя, period=начало квартала)
- `DataSource_Rosreestr_ETL_Plan_Apr26` — план интеграции в Stage 2a
- `DataSource_PerDeal_Reality_Apr26` — иерархия источников (1. Росреестр CSV → 2. ДОМ.РФ → 3. ЦБ ипотека → 4. Fedstat → 5. УПН Екб)
- `DataSource_UPN_Ekb_Apr26` — Уральская Палата Недвижимости (19 лет longitudinal по Екб)
**ДОМ.РФ фронт-API (по вкладкам):**
- `DomRF_Architecture_Apr26` · `DomRF_Host_Apr26` · `DomRF_API_PortalAnalytics_Apr26` · `DomRF_KeyAndLegal_Apr26` (ключ Basic MTpqd2U=)
- `DomRF_PlanA_Mapping_Apr26` — маппинг endpoints на 3 плитки Plan A
- 12 вкладок аналитики: `DomRF_Tab1_HousingIndicators_Apr26` ... `DomRF_Tab11_MortgageStats_Apr26`
- `DomRF_Spec_APF_v22` — официальный B2B API (только для банков)
- `DomRF_OfficialVsFront_Comparison_Apr26` — почему фронт незаменим даже с банк-партнёром
**НСПД (nspd.gov.ru, новый портал Росреестра):**
- `Rosreestr_SiteMap_Apr26` — карта ресурсов Росреестра/НСПД
- `NSPD_Architecture_Apr26` — React SPA, micro-frontends, OAuth через ESIA
- `NSPD_OAuth_Architecture_Apr26` — auth flow, JWT TTL=30 мин
- `NSPD_PhysicAccess_Apr26` — что доступно физик-аккаунту (18 сервисов, marketAnalytics ✓)
- `NSPD_MarketAnalytics_FullArchitecture_Apr26` ⭐ — полный API-флоу разобран в debug-браузере 26.04: saveUserFilters → graphEgrn*, tableEgrn, geomDataForHeatMap. Серверная сессия фильтров (userFiltersId)
- `NSPD_OrgOnly_Endpoints_Apr26` — graphEgrnCandleMedian/LineMedian возвращают 403 (абсолютные ₽/м² скрыты от physic, дублируют CSV-датасет)
- `NSPD_DataValue_For_GenDesign_Apr26` — value: 8 лет longitudinal, гранулярность до кадастрового квартала, GeoJSON-полигоны для heatmap
- `NSPD_AEGGIS_WMTS_Apr26` — WMTS-тайлы для embed в Mapbox/Leaflet
- `NSPD_PII_Leak_Apr26` · `Rosreestr_Recon_Findings_Apr26` · `Rosreestr_TLS_Note_Apr26` — security/инфра наблюдения
**Инфраструктура:**
- `Hosting_Pricing_Apr25` — сравнение провайдеров
- `Hosting_Decision_Apr25` — решение по Yandex Cloud (для будущей миграции)
- `Runbook_VPS_Setup_Beget` — пошаговая настройка production VM
- `SSH_Setup_Apr25` — локальная настройка SSH
- `DockerOps_Apr26` — multi-stage Dockerfile, npm ci, healthcheck fix, same-origin API
- `Production_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_dump
- `HTTPS_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://gendsgn.ru/docs)
- **Репо:** 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 (нет РФ-данных)