textmachine/platform/docs/STACK_DECISIONS.md

6.9 KiB
Raw Blame History

Стек платформы — пины и обоснования

Зонный документ platform/. Пины ниже сверены ЖИВЬЁМ 04.08.2026 (Go-прокси @latest, postgresql.org, go.dev/dl) — версии по памяти не называются. Библиотеки сессия не ратифицирует: таблица уходит оркестратору вместе с деревом.

Общая записка по обоим новым сервисам — frontend/docs/STACK_DECISIONS.md §5 (02.08). Здесь — платформенная часть с датами релизов и сверкой. Что изменилось за два дня: три библиотечных пина §5 (pgx · goose · River) на 04.08 всё ещё последние; по Go последним патчем стенда идёт 1.26.5 (07.07) — floor go.mod оставлен общим с движком, а тулчейн сборки поднят до 1.26.5 (см. ниже).

Пины

Что Пин Релиз пина Зачем нам
Go (язык, go.mod) 1.26.4 02.06.2026 Тот же floor, что у движка (backend/go.mod) — общий стенд собирает оба модуля одним тулчейном
Go (тулчейн сборки, make tools-check) ≥1.26.5 07.07.2026 1.26.5 несёт security-фиксы crypto/tls и os; сетевой модуль собирается ими, а не «чем-нибудь 1.26»
PostgreSQL 18.x (проверено на 18.4), floor 16 18.4 — май 2026 18 — текущая мажорная (19 в бете, в прод не берём); floor 16, потому что River тестируется на трёх последних мажорных
HTTP stdlib net/http + ServeMux Роутер-библиотека не нужна: ServeMux с 1.22 умеет метод+wildcards, а Request.Pattern даёт лог по маршруту, не по пути
CSRF stdlib http.CrossOriginProtection Go 1.25 Ровно тот механизм, что описан в §5 (Sec-Fetch-Site → Origin), теперь в тулчейне — свой велосипед не пишем
Postgres-драйвер github.com/jackc/pgx/v5 v5.10.0 03.06.2026 Живой pool, pgconn.PgError для проверки констрейнтов, stdlib для goose
Миграции github.com/pressly/goose/v3 v3.27.3 22.07.2026 Библиотекой + embed.FS; WithSessionLocker = advisory-лок, две реплики выкатываются по очереди
Очередь github.com/riverqueue/river v0.42.0 31.07.2026 Пин ПОДТВЕРЖДЁН живой сверкой, но в go.mod НЕ добавлен: П-3 вне скоупа P0, а зависимость без кода — мусор в графе
Линтер golangci-lint 2.12.2 06.05.2026 Тот же пин, что у движка: находки версионно-зависимы, разъезд пинов = разные гейты в одном репо
Уязвимости govulncheck v1.6.0 09.07.2026 Отдельная цель make vuln, не часть check: ей нужна сеть, а батарея обязана быть зелёной на голом клоне офлайн

Redis нет — архитектурное «нет» из §5 в силе: очередь, лизы и рейт-лимиты живут в том же Postgres.

Что решено этой сессией (сверх §5)

  1. /healthz/readyz. Liveness ничего не трогает (БД лежит — процесс жив), readiness пингует пул. Пустой TM_PLATFORM_DSN — легальный старт: сервис поднимается и честно говорит «не готов». Иначе супервизор убивает здоровый процесс за то, что база моргнула.
  2. Ops-эндпоинты вне версионного префикса. /healthz, /readyz — в корне; контрактная поверхность целиком под /v0 (базовый путь спеки платформа ПОДТВЕРЖДАЕТ).
  3. Один mux. Контрактные маршруты регистрируются с префиксом в паттерне, а не вложенным mux'ом под StripPrefix: вложенный получает КОПИЮ запроса, и Request.Pattern наружу не возвращается — лог пришлось бы писать по сырому пути с id книг. Проверено исполнением.
  4. Гард навешен на поддерево, а не на ручки. Неизвестный путь под /v0 отвечает 401 раньше 404: аноним не должен картографировать поверхность.
  5. Заголовки безопасности — на каждом ответе (X-Robots-Tag: noindex, Cache-Control: no-store, nosniff, no-referrer): ПТ-34 нельзя оставлять на дисциплину автора следующей ручки.
  6. Батарея зоны — make check (build · vet · fmt · lint · test -race), форма скопирована с backend/Makefile вплоть до именования пропущенных тестов: тихий skip читается как покрытие.
  7. Тесты с БД гейтятся TM_PLATFORM_TEST_DSN и создают СВОЮ базу на прогон (дропают в t.Cleanup). Батарея на голом клоне зелёная и офлайн; с DSN — та же батарея плюс схема.

Как поднять локально

export TM_PLATFORM_DSN='postgres://user@host:5432/tmplatform?sslmode=disable'
make check                        # батарея зоны
TM_PLATFORM_MIGRATE=1 go run ./cmd/tmplatformd   # миграции + сервер на 127.0.0.1:8080
curl -s localhost:8080/healthz    # ok
curl -s localhost:8080/readyz     # ready

Переменные: TM_PLATFORM_ADDR · TM_PLATFORM_DSN · TM_PLATFORM_MIGRATE · TM_PLATFORM_TRUSTED_ORIGINS (через запятую) · TM_PLATFORM_SESSION_IDLE · TM_PLATFORM_SESSION_MAX_AGE.

⚠ Postgres на стенде отсутствует как системный пакет и sudo нет. Схема и запросы этой сессии проверены на ЖИВОМ PostgreSQL 18.4, поднятом без root из бинарников zonky (io.zonky.test.postgres, Maven Central) в скрэтчпаде — вне репозитория и вне зависимостей модуля.