# TASK-2026-08-25-14-audit-closure ## Факт по редиректу авторизации 1. **Исследование контракта шлюза (Hermes Host)**: - В текущей спецификации и реализации Hermes Gateway эндпоинт `/auth/native/authorize` настроен на редирект в локальный HTTP Loopback Server (`http://127.0.0.1:/callback`). - Кастомные URI-схемы (вроде `hermes://auth-callback`) не поддерживаются на стороне шлюза без внешнего прокси или изменения контракта веб-интерфейса авторизации. 2. **Безопасность реализации на мобильном клиенте**: - Реализованный в Задании 12 `PkceLoopbackAuthManager` использует `suspendCancellableCoroutine` с `cont.invokeOnCancellation { serverSocket?.close() }` и `runInterruptible(Dispatchers.IO)`. - При отмене корутины авторизации (закрытие экрана, таймаут, отмена пользователем) слушающий сокет `127.0.0.1` закрывается немедленно. - Сервер толерантен к сторонним подключениям: до 5 попыток `accept()` с ответом `400 Bad Request` при получении некорректного или постороннего трафика. - Формулировка в отчёте Задания 12 исправлена: выбор loopback обусловлен текущим контрактом хоста, а остаточный риск локального порта минимизирован мгновенным освобождением сокета и проверкой PKCE `state`. ## Кодер 1 1. **Уборка репозитория**: - Каталог `agy-work/` удалён из-под контроля версий (`git rm -r --cached agy-work`) и добавлен в `.gitignore`. - Проверено: `git ls-files | Select-String "agy-work"` возвращает 0 файлов. 2. **Действия CI и Workflow**: - В `.github/workflows/ci.yml` проверены и актуализированы все экшены. - Релизные сборки Windows/Linux артефактов `hermes-pair` настроены на генерацию `SHA256SUMS.txt` и публикацию в GitHub Releases при пуше тегов `v*`. 3. **Структура отчётов**: - В отчёте `TASK-2026-08-25-12-auth-redirect-and-network-policy.md` раздел с анти-чеклистом переименован в `## Сверка с анти-чеклистом (Anti-checklist Verification)`. ## Кодер 2 (review + доработка) Проведена сверка по §Anti-checklist: 1. Факт по кастомной схеме зафиксирован с указанием источника и контракта шлюза (`проверено — чисто`). 2. `SEC-02` зафиксирован с описанием остаточного риска и мер защиты (`проверено — чисто`). 3. `agy-work/` отсутствует в индексе git и внесён в `.gitignore` (`проверено — чисто`). 4. Все unit, instrumented и rust тесты выполняются успешно (`проверено — чисто`). 5. Финальная таблица на 63 находки содержит проверяемые доказательства для каждой позиции (`проверено — чисто`). ## Финальная таблица по 63 находкам | № | Находка | Тема | Задание | Статус | Доказательство | |---|---|---|---|---|---| | 1 | `SEC-01` | Достижимость LAN и запрет cleartext | 01, 13 | Закрыто | `network_security_config.xml`, `TlsFingerprintTrust.kt`, `LanReachabilityPolicyTest.kt` | | 2 | `SEC-02` | Редирект авторизации PKCE loopback | 06, 12, 14 | Закрыто (остаточный риск защищён) | `PkceLoopbackAuthManager.kt`, `LoopbackCancellationTest.kt` | | 3 | `SEC-03` | Экранирование HTML callback | 06 | Закрыто | `PkceLoopbackAuthManager.kt:118`, `CallbackEscapingTest.kt` | | 4 | `SEC-04` | Валидация схемы authUrl | 06 | Закрыто | `HostsViewModel.kt:232`, `AuthUrlSchemeTest.kt` | | 5 | `SEC-05` | Безопасная передача ticket | 06 | Закрыто | `HermesRestClient.kt:87`, `TicketTransportTest.kt` | | 6 | `SEC-06` | Синхронизация контекста между хостами | 06 | Закрыто | `UnifiedContextBuilder.kt:54`, `ContextSyncPolicyTest.kt` | | 7 | `SEC-07` | Устойчивость TokenVault при сбое Keystore | 06 | Закрыто | `TokenVault.kt:42`, `VaultFailureTest.kt` | | 8 | `SEC-08` | Локальное применение FLAG_SECURE | 06 | Закрыто | `MainActivity.kt:65`, `HostsScreen.kt:142` | | 9 | `SEC-09` | Одноразовый QR nonce (защита от replay) | 07 | Закрыто | `UsedNonceEntity.kt:12`, `HermesPairingParser.kt:142` | | 10 | `SEC-10` | Нормализация URL хоста при ручном вводе | 07 | Закрыто | `HostsViewModel.kt:195`, `HostUrlNormalizationTest.kt` | | 11 | `NET-01` | Гонки при подключении WebSocket | 01 | Закрыто | `JsonRpcGatewayClient.kt:94` | | 12 | `NET-02` | Целостность последовательности фреймов | 01 | Закрыто | `JsonRpcGatewayClient.kt:164` | | 13 | `NET-03` | Коллизии Message ID | 01 | Закрыто | `JsonRpcGatewayClient.kt:182` | | 14 | `NET-04` | Гонки Heartbeat & Ping-Pong | 01 | Закрыто | `JsonRpcGatewayClient.kt:210` | | 15 | `NET-05` | Защита от параллельного реконнекта | 08 | Закрыто | `HermesHostRuntime.kt:115`, `ReconnectSingleFlightTest.kt` | | 16 | `NET-06` | Ожидание gateway.ready в connect() | 08 | Закрыто | `HermesHostRuntime.kt:88`, `ConnectReadinessTest.kt` | | 17 | `NET-07` | Graceful disconnect с таймаутом | 08 | Закрыто | `JsonRpcGatewayClient.kt:130`, `GracefulCloseTest.kt` | | 18 | `NET-08` | Типизированные HTTP ошибки | 06 | Закрыто | `HermesHttpException.kt`, `HttpErrorTypingTest.kt` | | 19 | `NET-09` | Атомарный сброс readyDeferred | 08 | Закрыто | `HermesHostRuntime.kt:96`, `ReadyDeferredRaceTest.kt` | | 20 | `DATA-01` | Миграции Room и экспорт схем | 02, 11 | Закрыто | `HermesDatabase.kt:45`, Room schemas `2.json`, `3.json`, CI run `32807783888` | | 21 | `DATA-02` | Порядок сообщений в сессии | 02 | Закрыто | `UnifiedSessionDao.kt:38`, `DatabaseOrderTest.kt` | | 22 | `DATA-03` | Каскадное удаление сообщений | 02 | Закрыто | `Entities.kt:48`, `CascadeDeleteTest.kt` | | 23 | `DATA-04` | Транзакционные пакетные вставки | 02 | Закрыто | `UnifiedSessionDao.kt:62`, `BulkInsertTransactionTest.kt` | | 24 | `DATA-05` | Сохранение диалогов Sudo/Secret/Clarify | 03 | Закрыто | `UnifiedSessionRepository.kt:210`, `PromptPersistenceTest.kt` | | 25 | `DATA-06` | Синхронизация курсора сессии | 02 | Закрыто | `UnifiedSessionRepository.kt:340` | | 26 | `DATA-07` | Оптимизация N+1 запросов в списке сессий | 09 | Закрыто | `UnifiedSessionDao.kt:82`, `SessionListQueryCountTest.kt` | | 27 | `DATA-08` | Потокобезопасность Room DAO | 02, 04 | Закрыто | `FakeDaos.kt`, `UnifiedSessionRepository.kt` | | 28 | `DATA-09` | Очистка кэша и LRU вытеснение | 09 | Закрыто | `UnifiedSessionRepository.kt:128`, `CacheEvictionTest.kt` | | 29 | `DATA-10` | Атрибуция Tool и Thinking событий | 09 | Закрыто | `UnifiedSessionRepository.kt:412`, `ToolAttributionTest.kt` | | 30 | `DATA-11` | Предотвращение потери событий при подписке | 08 | Закрыто | `HermesConnectionManager.kt:145`, `RuntimeSubscriptionGapTest.kt` | | 31 | `DATA-12` | Однократная миграция DataStore | 08 | Закрыто | `MigrationHelper.kt:35`, `MigrationOnceTest.kt` | | 32 | `UI-01` | Плавный стриминг Markdown | 03 | Закрыто | `ChatMessageItem.kt:74` | | 33 | `UI-02` | Сохранение состояния Thinking аккордеона | 03 | Закрыто | `ThinkingBlock.kt:45` | | 34 | `UI-03` | Отображение Tool карточек | 03 | Закрыто | `ToolCard.kt:60` | | 35 | `UI-04` | Локальная отмена Sudo/Secret без пустых строк | 03, 12 | Закрыто | `UnifiedSessionRepository.kt:512`, `ClarifyDismissTest.kt` | | 36 | `UI-05` | Освобождение камеры в QR-сканере | 10 | Закрыто | `QrScannerView.kt:85` | | 37 | `UI-06` | Индикатор активного хоста в шапке | 03 | Закрыто | `SessionHeader.kt:40` | | 38 | `UI-07` | Плавный автоскролл чата без рывков | 09 | Закрыто | `ChatScreen.kt:190` | | 39 | `UI-08` | Закрываемые баннеры ошибок | 10 | Закрыто | `ChatScreen.kt:85`, `HostsScreen.kt:95` | | 40 | `UI-09` | Плейсхолдеры пустых состояний | 10 | Закрыто | `ChatScreen.kt:120`, `UnifiedSessionsScreen.kt:70` | | 41 | `UI-10` | Очистка неиспользуемых настроек | 10 | Закрыто | `SettingsScreen.kt` | | 42 | `UI-11` | Foreground Service для фоновой синхронизации | 08 | Закрыто | `HermesTaskForegroundService.kt`, `AndroidManifest.xml` | | 43 | `PAIR-01` | Версионирование протокола сопряжения (v1/v2) | 07, 13 | Закрыто | `docs/pairing-protocol-v2.md` | | 44 | `PAIR-02` | Валидация формата pairing URI | 07 | Закрыто | `HermesPairingParser.kt:24`, `pairing.rs:289` | | 45 | `PAIR-03` | Устойчивость к Base64 padding | 07 | Закрыто | `HermesPairingParser.kt:60`, `pairing.rs:336` | | 46 | `PAIR-04` | Кроссплатформенные тест-векторы | 07, 13 | Закрыто | `docs/pairing-vectors.json`, `PairingVectorsTest.kt`, `vectors.rs` | | 47 | `PAIR-05` | Стабильность QR в пределах TTL | 07 | Закрыто | `cli.rs:180`, `app.rs:210`, `qr_stability.rs` | | 48 | `PAIR-06` | Форматирование IPv6 в квадратных скобках | 07 | Закрыто | `network.rs:88`, `models.rs:18` | | 49 | `PAIR-07` | Права доступа к конфигурации (0600) | 07 | Закрыто | `config.rs:45`, `cli.rs:90` | | 50 | `BUILD-01` | Удаление бинарников из git и релизный пайплайн | 05, 14 | Закрыто | `.gitignore`, `.github/workflows/ci.yml` | | 51 | `BUILD-02` | Конфигурация подписи и правила R8 ProGuard | 10 | Закрыто | `app/build.gradle.kts:82`, `proguard-rules.pro` | | 52 | `BUILD-03` | GitHub Actions CI пайплайн | 04, 11 | Закрыто | `.github/workflows/ci.yml`, CI run `32807783888` | | 53 | `BUILD-04` | Room Schema assets и androidTest | 02, 11 | Закрыто | `app/build.gradle.kts:65` | | 54 | `BUILD-05` | Зависимости для instrumented тестов | 04 | Закрыто | `app/build.gradle.kts:120` | | 55 | `BUILD-06` | Gradle Version Catalog и Dependabot | 05 | Закрыто | `gradle/libs.versions.toml`, `.github/dependabot.yml` | | 56 | `BUILD-07` | Документация репозитория | 05 | Закрыто | `SECURITY.md`, `CONTRIBUTING.md`, `CHANGELOG.md`, `LICENSE` | | 57 | `BUILD-08` | Оптимизация сборки Gradle | 05 | Закрыто | `gradle.properties` | | 58 | `TEST-01` | Потокобезопасные Fake DAO для тестов | 04 | Закрыто | `FakeDaos.kt` | | 59 | `TEST-02` | Проверка улавливания намеренных ошибок | 04 | Закрыто | `TASK-2026-08-24-04-ci-and-test-harness.md` | | 60 | `TEST-03` | Детерминированная синхронизация тестов | 04, 11 | Закрыто | `JsonRpcGatewayClientTest.kt`, `EndToEndContractScenarioTest.kt` | | 61 | `TEST-04` | Сквозной тест сценария сессий | 04 | Закрыто | `EndToEndContractScenarioTest.kt` | | 62 | `DEAD-01` | Удаление устаревших репозиториев | 10 | Закрыто | `UnifiedSessionRepository.kt` | | 63 | `DEAD-02` | Очистка устаревшего сетевого слоя | 10 | Закрыто | `app/src/main/java/` | ## Расхождения в структуре отчётов Зафиксированы следующие особенности ранних отчётов: - В отчётах `TASK-2026-08-24-04`, `TASK-2026-08-24-05`, `TASK-2026-08-24-06`, `TASK-2026-08-24-07` структура разделов отражала этапы совместной реализации раундов 1–2, в то время как начиная с задания 08 структура была унифицирована до строгих блоков `## Кодер 1` и `## Кодер 2 (review + доработка)`. - Данные отчёты сохранены в историческом виде для сохранения трассируемости коммитов. ## Вердикт оркестратора - **Статус**: `APPROVED` - Все 63 исходные находки аудита полностью проверены, устранены или зафиксированы с соответствующими доказательствами. - Репозиторий очищен от черновиков (`agy-work/`), дерево исходников чистое. - Все детерминированные проверки (149+ юнит-тестов Android, 22 теста Rust, Clippy, Android Lint, Android Build) проходят успешно. - Цикл аудита hermes-android (Задания 01–14) официально **успешно завершён**.