docs(agents): Claude PR4 review — gate PASS, deployment blocked on secrets/access
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
5040ba800c
commit
a39f958a98
1 changed files with 86 additions and 0 deletions
|
|
@ -0,0 +1,86 @@
|
||||||
|
# Claude — независимая проверка PR #4 и развёртывание Stage1 (ЧАСТИЧНЫЙ ОТЧЁТ)
|
||||||
|
|
||||||
|
Дата: 2026-10-19, домашний сервер (`server`, 10.77.0.3). Задание:
|
||||||
|
`agents/claude/inbox/2026-10-19-stage1-pr4-review-and-deploy.md`.
|
||||||
|
|
||||||
|
## SHA
|
||||||
|
- PR: https://git.ochenstarik.ru/ochenstarik/randomayzer/pulls/4
|
||||||
|
- Base на момент проверки: `13606008f16f53d50845cd7389a4c5d3813fec12`. Отличие от base в handoff (`52fb758`) —
|
||||||
|
только мой документ `agents/codex/inbox/2026-10-19-stage1-completion.md`.
|
||||||
|
- **Reviewed SHA: `5040ba800c5d87f8405997fb854c719e93932fec`**: runtime-файлы идентичны `cce70c0`, шаблоны proxy —
|
||||||
|
`c5ede46`. Между `930e6ee` и `5040ba8` только handoff-документы (проверено `git diff --name-only`).
|
||||||
|
- Merge SHA, deployed SHA, image ID — **нет, развёртывание не выполнялось** (см. блокеры).
|
||||||
|
|
||||||
|
## 1. Gate на reviewed SHA (отдельный worktree)
|
||||||
|
|
||||||
|
| Команда | exit | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| `npm ci` | 0 | 449 packages |
|
||||||
|
| `npx prisma generate` | 0 | Prisma Client 5.22.0 |
|
||||||
|
| `npm test` | 0 | 63 files, **380/380** |
|
||||||
|
| `npx tsc --noEmit` | 0 | без ошибок |
|
||||||
|
| `npm run lint` | 0 | 0 errors, 6 warnings |
|
||||||
|
| `npm run build` | 0 | Compiled successfully |
|
||||||
|
| `npm audit --omit=dev` | 0 | found 0 vulnerabilities (только production deps; dev-дерево не заявляется чистым) |
|
||||||
|
|
||||||
|
## 2. R2 — чистая PostgreSQL 16 (127.0.0.1:55439, новый volume `randomayzer-integration-pgdata`)
|
||||||
|
- До миграций: 0 таблиц в `public`.
|
||||||
|
- `prisma migrate deploy`: exit 0, 3 миграции (`20260818000000_initial`, `…120000_ownership_invariant`,
|
||||||
|
`20260821120000_persistent_auth_stores`).
|
||||||
|
- `npm run test:integration`: exit 0, **12/12**.
|
||||||
|
- `prisma migrate diff --from-url … --to-schema-datamodel … --exit-code`: exit 0, «No difference detected».
|
||||||
|
- Контейнер остановлен (`down`), свой тестовый volume удалён. Чужие volumes не трогались.
|
||||||
|
- `agents/codex/notes/validate-r5-templates.sh`: exit 0 — синтаксис Caddy 2.8 и HAProxy 3.0 на fake fixture.
|
||||||
|
**Это не приёмка живого VPS.**
|
||||||
|
|
||||||
|
## 3. Ревью кода
|
||||||
|
|
||||||
|
| Область | Итог |
|
||||||
|
|---|---|
|
||||||
|
| Seed-исключение | Только 4 assertion длины в `tests/randomizer.test.ts` и `tests/seed-precommit-gate.test.ts`, 32→64 hex — строже, не слабее. `generateCryptoSecureSeed` = 32 байта. HMAC, proof format и snapshot hash не тронуты. В `src/` нет валидации длины seed → прежние 32-hex розыгрыши продолжают проверяться. Совпадает с `agents/codex/inbox/2026-10-19-seed-owner-authorization.md`. |
|
||||||
|
| Malformed VK records (прежний HIGH) | **CLOSED** на reviewed SHA. `vk-provider.ts`/`vk-client.ts`: строгая проверка shape/ID/типов профилей, дублей, `count`, размера страницы, смены total и раннего конца → `VkIncompleteDataError`, «No result was saved». |
|
||||||
|
| Partial participant saves | Замена участников в одной `prisma.$transaction` (`deleteMany` + вставка) — частичного сохранения нет. |
|
||||||
|
| Mock-smoke (прежний MEDIUM) | **CLOSED**: preview отдаёт `providerMode: LIVE/MOCK` (`instanceof VkProvider`); smoke опирается на маркер. |
|
||||||
|
| Proxy socket-peer | `tools/production-transport.cjs`: все `x-forwarded-*`, `forwarded`, `x-real-ip`, `cf-connecting-ip` удаляются; доверие только при socket peer == `TRUSTED_PROXY_IP`. Значение — только `10.77.0.1`, в local запрещено. XFF принимается только как один IP; proto https — только от доверенного peer. |
|
||||||
|
| Профили | local: только `http://localhost/127.0.0.1/[::1]`; strict: только https. `VK_REDIRECT_URI` обязан быть `${origin}/api/auth/vk/callback`. CSRF в production сверяет полный origin. Secure cookie по профилю, HttpOnly, SameSite=Lax. |
|
||||||
|
| Compose | БД без host-порта, сеть `internal: true`; app `127.0.0.1:3100` (+`10.77.0.3:3100` в domain overlay), `cap_drop: ALL`, `no-new-privileges`, лимиты app 1g/1.5, PG 512m/1.0, `user: node`/`postgres`. |
|
||||||
|
| Backup/restore | `umask 077`, проверка 0600 env, `.partial` + `pg_restore --list`, восстановление в отдельную drill-БД с удалением, retention 14 дней. |
|
||||||
|
| Caddy template | basic_auth, `-Authorization` к upstream, вычистка `X-Real-IP`/`Forwarded`/`CF-Connecting-IP`, лимит тела 1 МБ, таймауты. |
|
||||||
|
|
||||||
|
### Findings
|
||||||
|
- **CRITICAL/HIGH: не найдено.**
|
||||||
|
- **MEDIUM (проверить вживую):** если `krona-proxy-mux` пропускает TLS к Caddy по SNI без PROXY protocol,
|
||||||
|
`{remote_host}` у Caddy = адрес контейнера HAProxy → приложение видит всех клиентов с одного IP. Тогда rate limit
|
||||||
|
по IP общий, аудит-IP неверен. Для сайта одного пользователя не блокирует; решение — PROXY protocol v2
|
||||||
|
HAProxy→Caddy, если он уже используется для других сайтов, иначе принять как debt.
|
||||||
|
- **MEDIUM (функционально, вживую):** на активном посте VK при пагинации может вернуть дубль ID
|
||||||
|
(лайк между страницами) → импорт отказывает целиком. Это fail-closed по дизайну, но живой импорт может часто
|
||||||
|
требовать повтора. Проверить в G на реальном посте; при частых отказах — отдельная задача (повтор/снимок).
|
||||||
|
- **LOW (известные):** COMMUNITY adminDetection metadata (маршруты не позволяют неподдерживаемую проверку);
|
||||||
|
нет HTTP→HTTPS redirect при только HTTP-01 маршруте. Решение — оставить LOW до живой проверки, не открывать
|
||||||
|
обычный HTTP к приложению.
|
||||||
|
- **LOW (новое):** ежедневные дампы лежат на том же системном SSD (занят на 85%, ресурс износа 19%) —
|
||||||
|
не offsite. Согласуется с решением владельца отложить offsite-бэкапы.
|
||||||
|
|
||||||
|
## 4. Предусловия развёртывания (проверено)
|
||||||
|
- Порт 3100 свободен; `krona-wg` 10.77.0.3/24 поднят; RAM свободно ~35 ГБ; диск `/` 85%.
|
||||||
|
- WG peer `10.77.0.1` = VPS 178.212.13.102 (совпадает SSH host key ed25519, проверено ранее 19.10).
|
||||||
|
- DNS `random.ochenstarik.ru` → 178.212.13.102 по публичным резолверам (Google, Cloudflare DoH);
|
||||||
|
домашний роутер `192.168.1.1` отдаёт устаревший 185.26.122.80 — проверять через публичный DNS.
|
||||||
|
- **SSH на VPS для Claude: нет** (`krona@10.77.0.1: Permission denied (publickey)`).
|
||||||
|
|
||||||
|
## Блокеры (развёртывание не начиналось)
|
||||||
|
1. **Секреты (владелец):** 0600-файл production env вне Git с VK ID `VK_APP_ID`/`VK_CLIENT_SECRET`,
|
||||||
|
`VK_SERVICE_TOKEN`, `AUTH_SECRET`, `TOKEN_ENCRYPTION_KEY`, `POSTGRES_PASSWORD`. Молча не генерирую.
|
||||||
|
2. **VK ID кабинет (владелец):** redirect URI `http://localhost:3100/api/auth/vk/callback` и
|
||||||
|
`https://random.ochenstarik.ru/api/auth/vk/callback`. Поддержка localhost этим приложением не гарантирована.
|
||||||
|
3. **VPS (владелец):** SSH-доступ для Claude или выполнение раздела 6 runbook владельцем. Без него R5 BLOCKED.
|
||||||
|
4. **Живой VK:** тестовый аккаунт, публичный пост с лайками и комментариями, restricted post, группа для подписки.
|
||||||
|
A–M: все **BLOCKED** до п. 1–2.
|
||||||
|
|
||||||
|
## Вердикты
|
||||||
|
- **PR review:** PASS (без CRITICAL/HIGH; 2 MEDIUM на живую проверку, LOW перечислены). Рекомендую merge в main.
|
||||||
|
- **Домашний deployment:** не выполнен — BLOCKED (секреты).
|
||||||
|
- **VPS/domain:** не выполнен — BLOCKED (доступ, секреты).
|
||||||
|
- **Live VK A–M:** не выполнялось — BLOCKED.
|
||||||
|
- **Рекомендация координатору:** этап не закрыт; после секретов и доступа — шаги 3–6 задания.
|
||||||
Loading…
Reference in a new issue