review(a57): нативный вход через agy принят с исправлениями

Проверено исполнением, а не по отчёту.

Работает. Профиль, где лежит только файл, записанный agy, признаётся
подключённым, и хаб этот файл не переписывает — главный критерий приёмки
выполнен. Поиск терминала честный: перечисляет проверенных кандидатов, а
DISPLAY, WAYLAND_DISPLAY, XAUTHORITY и DBUS_SESSION_BUS_ADDRESS внесены в
список разрешённых переменных, иначе окно терминала не открылось бы. На
сервере владельца найдены x-terminal-emulator, gnome-terminal,
xfce4-terminal, xterm.

Исправлено два дефекта.

1. Почта после входа искалась в google_accounts.json, auth.json и id_token.
   У свежего слота первых двух нет, а antigravity-oauth-token у владельца
   занимает 505 байт — id_token туда не помещается. Последняя попытка
   разбирала токен доступа как JWT, но ya29-токен Google не JWT и claims не
   несёт. Пустая почта отключает проверку двойников, и рост номеров слотов,
   починенный в 9641957, вернулся бы. Теперь почта запрашивается у UserInfo —
   тем же способом, каким её узнаёт браузерный вход. Отказ сети вход не
   роняет: аккаунт подключён, почта Н/Д.

2. В существующем тесте test_seq_token_prevents_stale_refresh_clobber строгая
   проверка была заменена на нестрогую. Прогнал исходную пять раз подряд и в
   полном наборе — проходит. Ослабление было лишним, вернул; добавленную
   исполнителем проверку seq оставил, она по делу.

Не выполнено исполнителем: живая проверка входа на сервере (P0-7.1) — вместо
неё двенадцать модульных тестов. Вход требует участия владельца, поэтому
проверить его сам не могу.

Неточности отчёта: «Release Gate 16/16» — это счёт внутри второго раздела, а
не итог гейта; обращения к UserInfo API в коде не было, оно добавлено здесь.

661 passed, 2 skipped; ruff чисто; релизный гейт пройден.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hermes Team 2026-09-01 14:54:59 +07:00
parent 14d1eb4304
commit 23e9ac1d6b
2 changed files with 17 additions and 5 deletions

View file

@ -381,12 +381,24 @@ def check_profile_native_auth_status(profile_id: str) -> tuple[bool, str | None,
if jwt_email and "@" in jwt_email:
email = jwt_email
# Токен доступа Google (ya29....) — не JWT, разбирать его как JWT
# бессмысленно. Почту по нему отдаёт UserInfo, и этим же путём её узнаёт
# браузерный вход. Без почты не срабатывает проверка двойников, и один
# аккаунт снова расползётся по слотам — ровно та беда, которую чинили.
#
# Спрашиваем провайдера, только если в самом профиле почты не нашлось:
# у свежего слота нет ни google_accounts.json, ни auth.json, а файл
# antigravity-oauth-token (505 байт у владельца) id_token не содержит.
if not email and access_token:
from antigravity_provider.router.profile_manager import ProfileAuthManager
try:
from antigravity_provider.oauth import fetch_user_email
jwt_email, _ = ProfileAuthManager.extract_jwt_identity(str(access_token))
if jwt_email and "@" in jwt_email:
email = jwt_email
remote_email = fetch_user_email(str(access_token))
if remote_email and "@" in remote_email:
email = remote_email.strip()
except Exception as exc:
# Отказ сети не должен ронять вход: аккаунт подключён, почта — Н/Д.
logger.info("Почту через UserInfo установить не удалось: %s", exc)
auth_data = {
"auth_method": auth_method,

View file

@ -78,7 +78,7 @@ def test_seq_token_prevents_stale_refresh_clobber():
snap_after_stale = store.refresh(force_scan=False, seq=seq_stale)
# Stale response must be rejected, retaining the fresh generation
assert snap_after_stale.generation >= gen_fresh
assert snap_after_stale.generation == gen_fresh
assert snap_after_stale.seq != seq_stale
assert store.refresh_skipped_total >= 1