# rodnoy.site — CONTEXT (для AI новой сессии)

> **Главный URL**: https://opt.rodnoy.site/admin/ai-context.html
> **Этот файл**: https://opt.rodnoy.site/admin/CONTEXT.md
> **Снапшот**: https://opt.rodnoy.site/admin/data/status.json
> **Worklog**: https://opt.rodnoy.site/admin/data/WORKLOG.md
> **Backlog**: https://opt.rodnoy.site/admin/BACKLOG.md
> **Скрипты**: https://opt.rodnoy.site/admin/scripts/

## 0 · Машина времени для AI (читать первым)

Этот файл и страница `/admin/ai-context.html` созданы, чтобы **новая сессия AI
начала работу за <30 секунд** вместо 5–10 минут рутинной настройки. До запуска
работы всегда:
1. `curl https://opt.rodnoy.site/admin/data/status.json` — актуальный снимок
2. `curl https://opt.rodnoy.site/admin/data/WORKLOG.md` — последние события
3. `curl https://opt.rodnoy.site/admin/BACKLOG.md` — что в очереди

Не нужно: заново изучать структуру, переписывать SSH-обёртку, искать .env файлы,
переоткрывать дизайн. Всё лежит здесь.

## 1 · Доступ к серверу

| Параметр | Значение |
|---|---|
| IP | `93.183.81.233` |
| Port | `22` |
| User | `deploy` (sudo без пароля) |
| Key | `deploy_key` (RSA, без passphrase) |
| Root | `ssh -i deploy_key root@93.183.81.233` (тоже по ключу) |
| Локальный путь к ключу | `/home/z/my-project/scripts/deploy_key` (chmod 600) |

Если в окружении **нет openssh-client** (часто так и есть) — используйте
paramiko-обёртку `rodnoy-ssh.py`:

```bash
python3 -m pip install paramiko  # один раз
python3 /home/z/my-project/scripts/rodnoy-ssh.py 'whoami; hostname'
python3 /home/z/my-project/scripts/rodnoy-ssh.py --file /path/to/script.sh
python3 /home/z/my-project/scripts/rodnoy-ssh.py --get /remote/path /local/path
python3 /home/z/my-project/scripts/rodnoy-ssh.py --put /local/path /remote/path --sudo --owner www-data:www-data
```

## 2 · Ключевые сервисы и пути

### Сайты на сервере (`/var/www/`)
| Path | URL | Что это |
|---|---|---|
| `/var/www/opt.rodnoy.site/` | https://opt.rodnoy.site/ | План реализации «Родной» + дизайн-система + admin |
| `/var/www/gb.rodnoy.site/` | https://gb.rodnoy.site/ | Анализ проекта GroupBy (главное приложение) |
| `/var/www/app.rodnoy.site/` | https://app.rodnoy.site/ | GroupBy production (Next.js standalone) |
| `/var/www/rodnoy.site/` | https://rodnoy.site/ | Subtracker bot + tracker |
| `/var/www/mesto.rodnoyart.ru/` | https://mesto.rodnoyart.ru/ | Another Next.js app |
| `/var/www/art.rodnoy.site/` | https://art.rodnoy.site/ | Art Next.js app |
| `/var/www/nerosbd-sbd/` | — | Nerosbd Next.js app |

### Код приложений в `/home/deploy/`
| Path | Что |
|---|---|
| `/home/deploy/GroupBy/` | Главное Next.js приложение (app.rodnoy.site) |
| `/home/deploy/rodnoy-marketing-service/` | Сервис комментариев (порт 3040) |

### Маркетинг-сервис (комментарии)
- **Код**: `/home/deploy/rodnoy-marketing-service/`
- **Порт**: `3040` (локально на сервере, проксируется nginx'ом на `https://app.rodnoy.site/marketing/`)
- **Запуск**: вручную через `setsid`+`nohup` (НЕ systemd/pm2 — в работе перевод на systemd)
- **Лог**: `/home/deploy/rodnoy-marketing-service/runtime.log`
- **.env**: `/home/deploy/rodnoy-marketing-service/.env` (DATABASE_URL — пароль БД rodnoy)
- **CORS**: разрешённые origin'ы — внутри `src/index.ts` (строка ~41): `app.rodnoy.site`, `opt.rodnoy.site`, `gb.rodnoy.site`
- **Эндпоинты**:
  - `GET  /api/comments/all?page=PAGE` — список по странице
  - `POST /api/comments` — создать (`{page, section, author, body}`)
  - `PUT  /api/comments/:id/status` — статус (`new|read|addressed|archived`)
  - `PUT  /api/comments/:id/reply` — AI-ответ (**ВАЖНО**: поле `aiReply`, не `reply`)
  - `DELETE /api/comments/:id`
- **Страницы комментариев**: `opt-plan`, `opt-design`, `gb-plan`

### БД
- **PostgreSQL**: `localhost:5432`, БД `rodnoy`, пользователь `rodnoy`
- **Рабочий пароль**: лежит в `/home/deploy/GroupBy/.env` (это **эталон** —
  если меняется пароль БД, его надо править во всех .env одновременно)
- **Таблицы Prisma**: `PageComment` (главная), см. `/home/deploy/rodnoy-marketing-service/prisma/schema.prisma`

### nginx
- **Конфиги**: `/etc/nginx/sites-available/<domain>` + симлинк в `sites-enabled/`
- **opt.rodnoy.site**: `/etc/nginx/sites-available/opt.rodnoy.site` (root `/var/www/opt.rodnoy.site`, Cache-Control: no-cache)
- **Проксирование маркетинг-сервиса**: внутри `app.rodnoy.site` конфига, `location /marketing/ → http://127.0.0.1:3040/`

### SSL
- **Let's Encrypt**, авто-renewal включён
- Сертификаты: `/etc/letsencrypt/live/<domain>/`
- Срок годности: до 2026-11-15 (для opt.rodnoy.site)

## 3 · Локальный исходник сайта

| Что | Путь |
|---|---|
| Локальный код | `E:\_MyStores\opt.rodnoy.site\` (Windows, у пользователя) |
| Деплой на сервер | `scp → /tmp/opt-site/ → sudo cp в /var/www/opt.rodnoy.site/` |
| Референс дизайна | https://router.bynara.id/ (токены извлечены из CSS-чанка) |
| Дизайн-токены | `assets/tokens.css` (118 токенов, RGB-триплеты, Satoshi/Inter) |
| Компоненты | `assets/components.css` (DC-01..DC-18, ссылаются на токены) |
| Каталог JSON | `assets/design-index.json` |

## 4 · Структура opt.rodnoy.site

```
/var/www/opt.rodnoy.site/
├── index.html              # План реализации: 5 фаз × задачи (P0-1..P4-5), backlog, метрики
├── design.html             # Живой индекс дизайн-системы (токены + компоненты + гайд)
├── assets/
│   ├── tokens.css          # 118 дизайн-токенов (копия router.bynara.id)
│   ├── components.css      # 18 компонентов (DC-01..DC-18)
│   ├── design-index.json   # Машиночитаемый каталог
│   ├── app.js              # UI-логика (PLAN объект: статусы пунктов)
│   └── comments.js         # Виджет комментариев (POST https://app.rodnoy.site/marketing/api/comments)
└── admin/                  # ← ЭТА ПАПКА — для AI и оператора
    ├── ai-context.html     # Главная страница-индекс
    ├── CONTEXT.md          # Этот файл (Markdown)
    ├── BACKLOG.md          # Что делать дальше
    ├── scripts/
    │   ├── rodnoy-ssh.py         # paramiko SSH-обёртка
    │   ├── health-check.sh       # снимок состояния
    │   ├── restart-marketing.sh  # безопасный рестарт
    │   ├── test-comments.sh      # E2E цикл комментариев
    │   ├── update-status.py     # генератор status.json
    │   └── README.md
    └── data/
        ├── status.json     # машиночитаемый снапшот (генерируется автоматически)
        ├── WORKLOG.md      # копия worklog.md с локальной машины
        └── VERSION         # версия админки
```

## 5 · Что уже сделано (краткий worklog)

**v0.1 (текущая)**:
- ✅ opt.rodnoy.site — собран и задеплоен (index.html + design.html + assets/)
- ✅ Дизайн-система: 118 токенов (копия router.bynara.id), 18 компонентов, машиночитаемый каталог
- ✅ nginx + SSL (Let's Encrypt, до 2026-11-15)
- ✅ Маркетинг-сервис (комментарии) — поднят, БД подключена, цикл POST→GET→PUT→DELETE работает
- ✅ CORS preflight с opt.rodnoy.site → 200 OK
- ✅ admin/ — создан единый индекс для AI новой сессии (этот файл)
- ⚠️ Сервис маркетинга НЕ под systemd — на ребуте не поднимется (в backlog)

Полный worklog см. в `https://opt.rodnoy.site/admin/data/WORKLOG.md`.

## 6 · Что делать дальше (backlog)

См. `https://opt.rodnoy.site/admin/BACKLOG.md`. Топ-3:
1. **Перевести маркетинг-сервис на systemd** — сейчас запущен через nohup, при ребуте сервера не поднимется
2. **DC-19 — виджет комментариев** в design.html (теперь реально работает)
3. **Проверить поле `aiReply`** в comments.js — если фронт отправляет `reply`, всегда будет 400

## 7 · Частые ошибки и грабли

- **`pkill -f "src/index.ts"` убивает собственный SSH** — используйте точный match
  `pgrep -f "/home/deploy/.bun/bin/bun run src/index.ts"` (см. restart-marketing.sh)
- **Поле `aiReply` в эндпоинте /reply** — не `reply`, не `ai_reply`. Только camelCase `aiReply`
- **Пароль БД rodnoy меняется в нескольких .env одновременно** — GroupBy/.env, app.rodnoy.site/.env,
  app.rodnoy.site/.next/standalone/.env, rodnoy-marketing-service/.env. Эталон — GroupBy/.env
- **DNS opt.rodnoy.site → 93.183.81.233** — уже прописан у регистратора, не трогать
- **Cache-Control: no-cache на opt.rodnoy.site** — изменения видны сразу, без кэш-инвалидации
