fix(web): в мастере подключения были выдуманные коды устройства
Владелец: «грок не даёт добавить https://x.ai/device» — страница отдаёт 404. Причина хуже опечатки в адресе. Веб-мастер для Grok и Codex не был подключён к серверу ВООБЩЕ. Он показывал жёстко вписанный адрес x.ai/device (настоящий — auth.x.ai/device, и тот приходит от провайдера полем verification_uri) и ВЫДУМАННЫЕ коды устройства GRK-7842 и CDX-9104. Пользователь вводил бы несуществующий код бесконечно. Это тот самый класс дефекта, который вычищали из десктопа в первом аудите, вернувшийся в новом коде. Выдуманные значения убраны. Пока поток не проведён через веб-API, шаг честно сообщает, что подключение через веб не реализовано, и указывает рабочий путь — десктопное приложение, где поток проведён полностью. Отдельно: тест test_headless_server_auth_matrix ТРЕБОВАЛ наличия "https://x.ai/device" в коде, то есть закреплял дефект как требование. Переписан на противоположное — запрещает выдуманные коды и зашитые адреса провайдеров. Тесты: 375 passed, ruff чисто. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
03d73f8d0b
commit
6b8a4aad78
2 changed files with 39 additions and 25 deletions
|
|
@ -1458,27 +1458,25 @@ function showWizardStep2(providerId) {
|
|||
let bodyHtml = '';
|
||||
|
||||
if (providerId === 'grok' || providerId === 'openai-codex') {
|
||||
// Здесь стояли ВЫДУМАННЫЕ код устройства (GRK-7842 / CDX-9104) и жёстко
|
||||
// вписанный адрес x.ai/device, который отдаёт 404. Мастер не был подключён
|
||||
// к серверу вовсе: пользователь вводил бы несуществующий код бесконечно.
|
||||
// Пока поток не проведён через API, честнее сказать правду и указать
|
||||
// рабочий путь, чем показывать правдоподобную пустышку.
|
||||
const providerName = providerId === 'grok' ? 'Grok (xAI)' : 'OpenAI Codex';
|
||||
bodyHtml = `
|
||||
<div style="margin-bottom:12px; font-size:13px; color:var(--text-secondary);">
|
||||
Шаг 2 из 3: Авторизация ${providerId === 'grok' ? 'Grok (xAI)' : 'OpenAI Codex'} (Device Code OAuth)
|
||||
Шаг 2 из 3: Авторизация ${providerName}
|
||||
</div>
|
||||
<div style="background:var(--surface-muted); padding:14px; border-radius:var(--radius-sm); border:1px solid var(--border-subtle); margin-bottom:14px;">
|
||||
<div style="font-weight:700; margin-bottom:6px;">1. Откройте ссылку на любом устройстве:</div>
|
||||
<div style="display:flex; gap:8px; margin-bottom:12px;">
|
||||
<input type="text" class="input-text" style="flex:1;" id="wiz-auth-url" value="${providerId === 'grok' ? 'https://x.ai/device' : 'https://auth.openai.com/device'}" readonly>
|
||||
<button class="btn btn-secondary btn-sm" onclick="navigator.clipboard.writeText(document.getElementById('wiz-auth-url').value); showToast('Ссылка скопирована', 'success');">📋 Копировать</button>
|
||||
</div>
|
||||
|
||||
<div style="font-weight:700; margin-bottom:6px;">2. Введите код подтверждения:</div>
|
||||
<div style="display:flex; align-items:center; gap:12px; margin-bottom:12px;">
|
||||
<div style="font-family:var(--font-mono); font-size:22px; font-weight:700; color:var(--text-accent); letter-spacing:2px;" id="wiz-auth-code">
|
||||
${providerId === 'grok' ? 'GRK-7842' : 'CDX-9104'}
|
||||
</div>
|
||||
<button class="btn btn-secondary btn-sm" onclick="navigator.clipboard.writeText(document.getElementById('wiz-auth-code').innerText); showToast('Код скопирован', 'success');">📋 Копировать код</button>
|
||||
</div>
|
||||
|
||||
<div style="font-size:11px; color:var(--text-muted);">
|
||||
3. Подтвердите доступ в браузере. Hub автоматически зафиксирует авторизацию.
|
||||
<div class="modal-feedback warning" style="margin-bottom:14px;">
|
||||
<strong>Подключение через веб-интерфейс пока не реализовано.</strong><br>
|
||||
Вход по коду устройства выполняется на стороне сервера, и этот поток
|
||||
ещё не выведен в веб-API. Показывать здесь код было бы обманом:
|
||||
настоящий код выдаёт провайдер, а не интерфейс.
|
||||
<div style="margin-top:8px;">
|
||||
<strong>Рабочий путь:</strong> подключите аккаунт в десктопном
|
||||
приложении Hermes Hub — там поток проведён полностью и получает
|
||||
настоящий адрес и код от провайдера.
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -87,17 +87,33 @@ def test_account_card_compact_height_and_quota_rendering():
|
|||
|
||||
|
||||
def test_headless_server_auth_matrix():
|
||||
"""Verify headless server honesty in Add Account Wizard (Grok/Codex device-code vs Antigravity/Claude redirect warning)."""
|
||||
"""Клиент не должен показывать выдуманные коды и зашитые адреса провайдеров.
|
||||
|
||||
Раньше этот тест ТРЕБОВАЛ наличия "https://x.ai/device" в коде — то есть
|
||||
закреплял дефект как требование. Адрес отдаёт 404, а рядом стояли
|
||||
выдуманные коды устройства GRK-7842 и CDX-9104: мастер не был подключён к
|
||||
серверу, и пользователь вводил бы несуществующий код бесконечно.
|
||||
Настоящие адрес и код выдаёт провайдер в ответе device-flow.
|
||||
"""
|
||||
app_js = (STATIC_DIR / "app.js").read_text(encoding="utf-8")
|
||||
assert "Device Code OAuth" in app_js
|
||||
assert "https://x.ai/device" in app_js
|
||||
assert "https://auth.openai.com/device" in app_js
|
||||
# Проверяем суть, а не дословную формулировку: текст правился уже дважды,
|
||||
# и тест на точную фразу падал, хотя поведение оставалось верным.
|
||||
|
||||
for fake in ("GRK-7842", "CDX-9104"):
|
||||
assert app_js.count(fake) <= 1, (
|
||||
f"выдуманный код устройства {fake} снова показывается пользователю"
|
||||
)
|
||||
|
||||
for line in app_js.splitlines():
|
||||
if line.lstrip().startswith("//"):
|
||||
continue
|
||||
assert "x.ai/device" not in line, (
|
||||
"зашитый адрес x.ai/device вернулся в интерфейс; он отдаёт 404, "
|
||||
"настоящий приходит от провайдера в verification_uri"
|
||||
)
|
||||
|
||||
# Честность про сервер без экрана должна остаться.
|
||||
assert "Headless" in app_js, "нет предупреждения про сервер без экрана"
|
||||
assert "agy" in app_js, "не сказано, что вход идёт через консоль agy"
|
||||
assert "launcher/main.py" not in app_js, "инструкция ведёт на несуществующий файл"
|
||||
assert "ssh -L 8085:localhost:8085" in app_js
|
||||
|
||||
|
||||
def test_actions_contract_handling():
|
||||
|
|
|
|||
Loading…
Reference in a new issue