Commit graph

22 commits

Author SHA1 Message Date
5fb5675871 fix(tradein/security): defense-in-depth trusted-header auth + rate-limiter fix (#2213) (#2229)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-browser (push) Successful in 35s
Deploy Trade-In / build-frontend (push) Successful in 38s
Deploy / build-worker (push) Successful in 42s
Deploy / build-backend (push) Successful in 43s
Deploy / build-frontend (push) Successful in 42s
Deploy / deploy (push) Successful in 1m32s
Deploy Trade-In / test (push) Successful in 1m50s
Deploy Trade-In / build-backend (push) Successful in 52s
Deploy Trade-In / deploy (push) Successful in 51s
2026-07-02 21:15:58 +00:00
bb54de6000 feat(tradein/sale-share): standalone «Поиск домов» — de-Mera + gendsgn.ru/sale-share
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Поиск домов (доля квартир в продаже) вынесен в отдельный продукт, отвязан от
бренда «Мера» (Мера = оценка вторички). Только UI + 1 строка Caddy, бэк не тронут.

- app/sale-share/layout.tsx: своя metadata (title «Поиск домов — gendsgn»).
- components/trade-in/SaleShareHeader.tsx: своя шапка — продукт «Поиск домов»,
  без MeraMark и Mera-табов; UserMenu (auth) сохранён.
- app/sale-share/page.tsx: Topbar → SaleShareHeader; убраны «Мера» из
  breadcrumb/footer. Функционал/API (/trade-in/api/...) не тронут.
- Caddyfile: gendsgn.ru/sale-share → redir /trade-in/sale-share (короткий адрес;
  basePath=/trade-in → true vanity-URL требует отдельного app).
2026-06-29 01:09:26 +03:00
eb251ba7e7 ci(infra): coverage-gate (#68) + OpenAPI codegen-assert (#69) + uptime monitoring (#75)
All checks were successful
CI / changes (push) Successful in 13s
CI / changes (pull_request) Successful in 12s
CI / frontend-tests (push) Successful in 53s
CI / openapi-codegen-check (push) Successful in 1m58s
CI / frontend-tests (pull_request) Successful in 47s
CI / openapi-codegen-check (pull_request) Successful in 1m50s
CI / backend-tests (push) Successful in 8m54s
CI / backend-tests (pull_request) Successful in 8m45s
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 2m50s
Deploy / build-frontend (push) Successful in 3m11s
Deploy / build-worker (push) Successful in 4m38s
Deploy / deploy (push) Successful in 2m1s
#68: pytest-cov + [tool.coverage] fail_under=65 (baseline 71%), backend-tests --cov + xml.
#69: openapi-codegen-check job (dump app.openapi() → openapi-typescript → git diff).
  Job использует node_modules-pinned openapi-typescript/prettier (НЕ npx --yes latest —
  иначе version-mismatch ложный diff). + regenerated api-types.ts из СВЕЖЕГО main openapi
  (8288 строк, включая #73 /freshness — синхронен).
#75: Uptime Kuma isolated stack + status.gendsgn.ru Caddy + external Telegram watchdog.
#77: no change — build cache достаточен.

Closes #68
Closes #69
Closes #75
Closes #77
2026-06-13 23:28:06 +05:00
547ab37597 hotfix(caddy): named matcher @uipreview — handle не принимает несколько inline-путей → caddy crash-loop, прод down (#801) 2026-05-30 18:52:09 +00:00
b779376f9d fix(caddy): exempt /trade-in/_next/static/* too — CSS/JS на ui-preview грузились под auth → 401 (#801) 2026-05-30 18:47:01 +00:00
84f6d57d9d chore(caddy): exempt /trade-in/ui-preview/* from basic_auth (#801)
Public CI surface для a11y/lighthouse аудита. /ui-preview/estimate (#803) рендерит mock-фикстуру без бэкенда, но Caddy basic_auth отдавал 401. handle-блок ДО auth-import → публично.
2026-05-30 18:21:34 +00:00
88cdfd6adb feat(rbac): role-based access control via X-Authenticated-User middleware (#585)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Successful in 27s
Deploy / build-frontend (push) Successful in 30s
Deploy Trade-In / build-backend (push) Successful in 1m8s
Deploy Trade-In / deploy (push) Successful in 45s
Deploy / build-backend (push) Successful in 2m40s
Deploy / build-worker (push) Successful in 3m20s
Deploy / deploy (push) Successful in 1m16s
Backend RBAC + Caddy header_up. Closes part of #fixes-rbac-pra.
2026-05-26 06:18:40 +00:00
0e294641a1 fix(security): log_credentials + auth_audit.log → username из 401 (#436)
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Successful in 36s
Deploy / build-worker (push) Successful in 36s
Deploy / build-frontend (push) Successful in 42s
Deploy / deploy (push) Successful in 57s
2026-05-23 09:59:50 +00:00
cc2d148967 feat(security): закрыть gendsgn.ru basic_auth gate (multi-user, 11 users) (#426)
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-worker (push) Successful in 30s
Deploy / build-frontend (push) Successful in 28s
Deploy / build-backend (push) Successful in 31s
Deploy / deploy (push) Successful in 53s
Pilot demo 28.05.2026: closed gendsgn.ru/* (включая trade-in/) basic_auth gate. /health и /preview/* остаются public через route { } wrapper (Caddy 2.x directive ordering fix).

11 users (admin + user1..user10), bcrypt cost=14, snippet в git (audit trail). Scripts: scripts/auth/{add,remove,list}_user.sh.

Fixup PR #426 (route{} wrap + log rotation + base64 busybox-compat + runbook audit log fix).
2026-05-23 08:16:10 +00:00
lekss361
2ce29973f9 fix(tradein): Caddy strip только /trade-in для API (не /trade-in/api)
handle_path /trade-in/api/* стрипал /trade-in/api целиком — FastAPI
получал /v1/trade-in/estimate и возвращал 404. FastAPI router на
/api/v1/trade-in/*, нужен strip только префикса basePath /trade-in.
2026-05-21 01:17:24 +03:00
lekss361
b2841a761d fix(tradein): Caddy matcher для /trade-in без trailing slash
handle /trade-in/* НЕ матчил /trade-in (без слеша) — request попадал в
универсальный handle и проксировался на основной gendesign frontend,
который для unknown path отдавал 200 OK с пустым body.

Заменил на named matcher `@tradein path /trade-in /trade-in/*` — ловит
оба случая. Также убрал redirect-handle /trade-in → /trade-in/ т.к.
trailingSlash=false у Next.js и сам редиректит обратно.
2026-05-21 01:10:36 +03:00
lekss361
02267d0306 feat: add tradein-mvp subproject (Trade-In Estimator под /trade-in)
- FastAPI backend: PostGIS estimator + 3 scrapers (Avito/Cian/Yandex)
- Next.js 15 frontend: tradein.html mockup design, basePath=/trade-in
- WeasyPrint PDF (Брусника-style 4-page report)
- Address autocomplete с typo-tolerance + 6 EKB presets
- Изолированный docker stack gendesign-tradein (отдельная postgres БД)
- Caddy inline routes: gendsgn.ru/trade-in/* и /trade-in/api/v1/*
- Forgejo Actions: .forgejo/workflows/deploy-tradein.yml (shell-based GHCR login)
- Триггер только по paths: tradein-mvp/** (не пересекается с deploy.yml)
- Образы: ghcr.io/lekss361/gendesign-tradein-{backend,frontend}:latest

Первый запуск на сервере (вручную, один раз):
  - создать /opt/gendesign/tradein-mvp/.env.runtime (postgres pwd, contact email)
  - docker network create gendesign_shared (если нет)
  - docker compose -p gendesign-tradein up -d
  - docker compose -p gendesign exec caddy caddy reload
2026-05-21 00:25:39 +03:00
lekss361
7a2ba4d35a chore(preview): remove basic auth от /preview/* — публичный доступ 2026-05-17 11:37:41 +03:00
lekss361
f1bc821c2b feat(preview): add static mockups behind basic auth at /preview/*
4 HTML mockups (landing/site-finder/analytics/monitoring) — alternative
designs для audit-review без замены существующих React-страниц.

- Caddy file_server на handle_path /preview/* (внутри gendsgn.ru block)
- Bind mount ./preview:/srv/preview:ro в caddy container
- basic auth: user=preview / pwd shared via private channel
- Static, isolated — не влияет на /, /site-finder, /analytics (Next.js routes)
2026-05-17 11:15:13 +03:00
lekss361
82931897dd fix(infra): restore git.gendsgn.ru block in Caddyfile
Block был добавлен вручную при Forgejo migration (2026-05-16) но не
закоммичен в repo. Первый Caddyfile-touching deploy (#205 GlitchTip)
сделал git reset --hard origin/main на VPS → блок исчез → TLS handshake
internal error 80 на git.gendsgn.ru (prod down ~16:30).

Routes git.gendsgn.ru → forgejo:3000 (контейнер из forgejo-migration/
docker-compose.yml, shared gendesign_default network, Forgejo default
HTTP port).

VPS уже починен hotfix-ом руками; этот PR делает fix permanent — переживёт
любой git reset --hard от deploy.yml.
2026-05-16 19:51:54 +03:00
d3aa96336b feat(infra): GlitchTip self-hosted error tracking (#204 devops) (#205)
Some checks failed
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Has been cancelled
Deploy / build-worker (push) Has been cancelled
2026-05-16 15:08:50 +00:00
50547dcbb3 test(deploy): validate Forgejo Actions end-to-end flow (#189)
Some checks failed
CI / backend (push) Successful in 1m40s
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Failing after 11s
Deploy / build-worker (push) Failing after 11s
CI / frontend (push) Successful in 2m13s
Deploy / build-frontend (push) Failing after 12s
Deploy / deploy (push) Failing after 0s
2026-05-15 21:55:04 +00:00
lekss361
b0f5c38894 feat(deploy): split obsidian stack from main + path-filtered GHA
Obsidian Self-hosted LiveSync (CouchDB) выведен в отдельный docker-compose
stack и GHA workflow. Любой стек теперь редеплоится независимо.

* docker-compose.obsidian.yml: только couchdb в shared external network
* docker-compose.prod.yml: убрана couchdb-секция; caddy подключён к
  shared network для маршрута obsidian.gendsgn.ru → couchdb:5984
* .github/workflows/deploy-obsidian.yml: новый workflow с path-filters
  (триггерится только при изменениях obsidian-related файлов)
* .github/workflows/deploy.yml: + path-filters (триггерится только при
  main-related файлах) + создание shared network в bootstrap
* docs/obsidian-livesync.md: обновлены инструкции под split-архитектуру

После push:
1. ssh gendesign 'docker network create gendesign_shared'  (один раз)
2. Прописать COUCHDB_USER/PASSWORD в backend/.env.runtime
3. Добавить DNS A-record obsidian.gendsgn.ru → IP VPS
4. git push → GHA задеплоит обе части независимо

Преимущества:
- Изменения main не разрывают LiveSync клиентов
- Изменения obsidian не рестартуют main
- Падение obsidian-стека не влияет на основное приложение
2026-05-11 09:51:31 +03:00
lekss361
68e95aa1ce ops: real domain in Caddyfile + ignore egg-info 2026-04-26 12:49:20 +03:00
lekss361
e22aeb9b5a Docker: multi-stage backend, npm ci, healthcheck fix, same-origin API
- backend/Dockerfile: split builder/runner, runtime libs only, non-root app user, curl for healthcheck, --frozen via new uv.lock
- frontend/Dockerfile: npm ci instead of npm install (deterministic), USER node
- docker-compose.prod.yml: working backend healthcheck (curl now in image), redis healthcheck, drop dead NEXT_PUBLIC_API_BASE_URL env (Next.js bakes NEXT_PUBLIC_* at build time, runtime override is no-op)
- docker-compose.yml: same redis healthcheck, BACKEND_URL for next.config rewrites, drop uv from CMD (not in new image)
- Caddyfile: handle (not handle_path) so /api prefix is preserved into FastAPI router
- next.config.ts: rewrite /api/* and /health to BACKEND_URL in dev (no Caddy locally)
- frontend/src/lib/api.ts: empty default = same-origin relative URLs
- Makefile: drop uv run from migrate target
- Add backend/uv.lock and frontend/package-lock.json for reproducible builds

Verified: docker build succeeds for both, backend container starts, /health responds, curl healthcheck works inside image, container runs as non-root.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 10:47:35 +03:00
lekss361
c8b2cc8152 fix 2026-04-25 20:59:26 +03:00
lekss361
b95559eac9 init 2026-04-25 13:45:19 +03:00