feat(tradein/caddy): снять basic_auth с /trade-in — своя авторизация (#2558) #2569

Merged
lekss361 merged 2 commits from feat/tradein-caddy-cutover into main 2026-07-30 21:52:01 +00:00
Owner

Часть #2558 (эпик #2549, cutover). ⚠️ Не мержить раньше фикса навигации (fix/tradein-team-nav-and-401) — иначе пользователь попадёт на форму входа, но раздел «Команда» из v2-навигации по-прежнему недостижим.

Оба trade-in-блока (handle /trade-in/api/*, @tradein) + @saleshare-редирект перенесены выше import caddy/users.caddy.snippet → short-circuit до auth-гейта (тот же механизм, что уже у /health, /preview/*, @uipreview). Site Finder (/api/*, handle {}) остаётся под basic_auth без изменений.

Ключевое по безопасности. После снятия гейта {http.auth.user.id} пуст. Вместо того чтобы полагаться на неподтверждённое поведение header_up <field> <empty> (может не установить заголовок → клиентский X-Authenticated-User прошёл бы насквозь, а backend в AUTH_MODE=dual всё ещё принимает legacy trusted-header путь = внешняя подмена личности), применено документированное явное удаление header_up -X-Authenticated-User в обоих блоках. X-Internal-Auth-Secret из env (#2213) не тронут.

@saleshare перенесён тоже: он ведёт на /trade-in/sale-share, который теперь публичен — оставить короткую ссылку строже целевой страницы было бы несогласованно.

Валидация: caddy validate --adapter caddyfile в официальном образе caddy:2 локально (со смонтированным snippet) → Valid configuration. Прод не трогался, reload сделает деплой.

Последствия после мержа: тестовые учётки admintest/pilottest/analysttest/expiredtest есть только в roles.yaml, в tradein_users не мигрировались → потеряют доступ к Мере (боевые 13 имеют пароли, вход проверен). Follow-up на заметку: legacy dual-mode путь для trade-in становится мёртвым (всегда 401 без cookie) — можно рассмотреть AUTH_MODE=db_only отдельным issue.

Post-deploy smoke: /trade-in без basic-auth → форма входа; / и /api/* Site Finder → по-прежнему 401 basic_auth.

Часть #2558 (эпик #2549, cutover). ⚠️ **Не мержить раньше фикса навигации** (`fix/tradein-team-nav-and-401`) — иначе пользователь попадёт на форму входа, но раздел «Команда» из v2-навигации по-прежнему недостижим. Оба trade-in-блока (`handle /trade-in/api/*`, `@tradein`) + `@saleshare`-редирект перенесены **выше** `import caddy/users.caddy.snippet` → short-circuit до auth-гейта (тот же механизм, что уже у `/health`, `/preview/*`, `@uipreview`). Site Finder (`/api/*`, `handle {}`) остаётся под basic_auth без изменений. **Ключевое по безопасности.** После снятия гейта `{http.auth.user.id}` пуст. Вместо того чтобы полагаться на неподтверждённое поведение `header_up <field> <empty>` (может не установить заголовок → клиентский `X-Authenticated-User` прошёл бы насквозь, а backend в `AUTH_MODE=dual` всё ещё принимает legacy trusted-header путь = внешняя подмена личности), применено документированное явное удаление `header_up -X-Authenticated-User` в обоих блоках. `X-Internal-Auth-Secret` из env (#2213) не тронут. `@saleshare` перенесён тоже: он ведёт на `/trade-in/sale-share`, который теперь публичен — оставить короткую ссылку строже целевой страницы было бы несогласованно. Валидация: `caddy validate --adapter caddyfile` в официальном образе `caddy:2` локально (со смонтированным snippet) → `Valid configuration`. Прод не трогался, reload сделает деплой. **Последствия после мержа:** тестовые учётки `admintest`/`pilottest`/`analysttest`/`expiredtest` есть только в roles.yaml, в `tradein_users` не мигрировались → потеряют доступ к Мере (боевые 13 имеют пароли, вход проверен). Follow-up на заметку: legacy dual-mode путь для trade-in становится мёртвым (всегда 401 без cookie) — можно рассмотреть `AUTH_MODE=db_only` отдельным issue. Post-deploy smoke: `/trade-in` без basic-auth → форма входа; `/` и `/api/*` Site Finder → по-прежнему 401 basic_auth.
lekss361 added 1 commit 2026-07-30 21:06:44 +00:00
feat(tradein/caddy): снять basic_auth с /trade-in — своя авторизация (#2558)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
01bf4a91e4
Оба trade-in блока (`handle /trade-in/api/*`, `@tradein`) + связанный
`@saleshare` редирект перенесены ВЫШЕ `import caddy/users.caddy.snippet`
в route{} — Caddy матчит handle-блоки сверху вниз, поэтому они теперь
short-circuit'ят до basic_auth-гейта (тот же механизм, что уже применён
к /health, /preview/*, @uipreview). Site Finder (/, /api/*, /analytics)
остаётся под basic_auth без изменений.

Trade-in уже имеет собственную авторизацию (форма входа + opaque
session-cookie, #2552) поверх RBAC внутри tradein-backend — Caddy
basic_auth для него стал избыточным легаси-слоем.

Security: после переноса плейсхолдер {http.auth.user.id} для этих
блоков никогда не резолвится (basic_auth больше не выполняется на
пути к ним). Вместо `header_up X-Authenticated-User {http.auth.user.id}`
(Set-операция с пустым значением — недокументированно надёжна как
удаление заголовка) используется явное `header_up -X-Authenticated-User`
(документированная delete-семантика `-<field>`). Это исключает проход
клиентского X-Authenticated-User насквозь к tradein-backend, который
в auth_mode="dual" всё ещё принимает legacy trusted-header путь —
без явного удаления внешний запрос с подделанным заголовком мог бы
выдать себя за другого пользователя. X-Internal-Auth-Secret не тронут
(#2213, всегда перезаписывается из env).

Провалидировано: `caddy validate --config Caddyfile --adapter caddyfile`
(caddy:2 образ, локальный docker) → "Valid configuration".
bot-backend added 1 commit 2026-07-30 21:19:57 +00:00
docs(tradein/caddy): исправить обоснование scrub + scrub в ui-preview (#2558)
All checks were successful
CI / changes (pull_request) Successful in 14s
CI Trade-In / changes (pull_request) Successful in 14s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
2b24408c3f
Deep-review PR #2569 (echo-стенд на caddy:2, caddy adapt): комментарий у
/trade-in/api* и @tradein утверждал, что старая Set-форма
(header_up X-Authenticated-User {http.auth.user.id}) пропустила бы клиентский
заголовок насквозь — измерено, что это неверно. Caddy подставляет
неразрешённый плейсхолдер как литеральную строку (ReplaceKnown), т.е. старая
форма была бы fail-closed-but-сломанной (get_role("{http.auth.user.id}") ->
403 для всех), а не bypass. Решение (-Field вместо Set) остаётся правильным
по другой причине: это единственная форма с документированной delete-
семантикой, не зависящая от трактовки пустого/нерезолвленного плейсхолдера.

Также: @uipreview (единственный блок в trade-in-периметре без scrub) теперь
тоже явно удаляет X-Authenticated-User - единообразие периметра, хоть
сейчас и инертно (статичная страница без секрета).

И: комментарий у @saleshare уточнён - снятие Caddy basic_auth с
/trade-in/sale-share не делает страницу публичной, она по-прежнему за
RouteGuard + session-required API (редирект на /login без валидной сессии).

Провалидировано: caddy validate --config Caddyfile --adapter caddyfile
(caddy:2, локальный docker) -> "Valid configuration".
lekss361 merged commit f6b68b6eca into main 2026-07-30 21:52:01 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2569
No description provided.