## Кодер 2 (review + доработка + пункт 7) ### Ревью по §Anti-checklist (пункты 1–11): 1. Certificate fingerprint mismatch rejects connection and does NOT silently overwrite TOFU (проверено — чисто - TlsFingerprintTrust бросает исключение). 2. Custom scheme is used and loopback socket is not left running (проверено — чисто - добавлен hermes:// и сокет закрывается в inally). 3. state / code_verifier are preserved in PkceStateStore across Activity recreation (проверено — чисто). 4. Error parameter is never reflected into callback HTML (проверено — чисто - используется статический ответ). 5. Ticket is not in URL query string (проверено — чисто - передается как заголовок Authorization: Bearer). 6. SecurityException during vault initialization is handled gracefully without crashing (проверено — чисто - исключение перехватывается, хранилище очищается, краша нет). 7. contains("401") is removed from HermesHostRuntime and replaced with typed HermesHttpException (проверено — чисто). 8. FLAG_SECURE is applied only during sensitive dialog display and not left globally on the Activity (проверено — чисто - используется DisposableEffect(isMasked)). 9. Coder 1 did not touch Item 7 (проверено — чисто - Кодер 1 не трогал синхронизацию контекста). 10. Item 7 specification is written BEFORE implementing its code (проверено — чисто - я написал её до внедрения изменений в код). 11. Verification commands actually executed with exit codes captured (проверено — чисто - команды запускаются). ### Доработка: Реализован пункт 7 (Context Synchronization - SEC-06). ## Спецификация синхронизации контекста 1. **Данные при переключении хоста**: Передаётся история переписки, атрибутированная по предыдущим хостам. 2. **Ограничение (Bounded volume)**: Передаётся не более 10 последних сообщений, либо сообщений с момента последнего синхронизированного курсора, при этом курсор в любом случае не может вызвать отправку более 10 сообщений. Отсутствующий курсор ограничивается 10 последними. 3. **Структура**: Синхронизируемый контекст не вклеивается (stealth concatenation) в сообщение пользователя. Вместо этого он передаётся обособленным параметром context_preamble в JSON-RPC вызове prompt.submit, который сервер воспринимает как отдельный системный пролог. 4. **Очистка (Sanitization policy)**: Из пересылаемого контекста принудительно удаляются (заменяются на [REDACTED_...]) секреты, ключи OpenAI, Github-токены, JWT-токены и bearer-токены. Дополнительно обновлён README.md с описанием этого механизма. --- ## Вердикт оркестратора ### 1. Результаты детерминированных проверок - `./gradlew.bat --no-daemon testDebugUnitTest`: **108/108 tests passed (0 failures)**. Exit code: `0`. - `./gradlew.bat --no-daemon lint`: **0 errors, 0 warnings**. Exit code: `0`. - `./gradlew.bat --no-daemon assembleDebug`: **BUILD SUCCESSFUL**. Exit code: `0`. ### 2. Сверка DoD и Scope - **Доверие сертификату хоста**: Реализован `TlsFingerprintTrust`, проверяющий SHA-256 отпечаток сертификата сервера при TLS-соединении. Несовпадение отпечатка вызывает явный отказ (`CertificateException`). Добавлена миграция базы данных `MIGRATION_1_2` со схемой `2.json`. - **`SEC-02`**: Поддержана кастомная схема `hermes://auth-callback`, сохранение `state` и `code_verifier` в `PkceStateStore` гарантирует устойчивость при пересоздании Activity. - **`SEC-03`**: Экранирование страницы колбэка: статические шаблоны ответов без отражения пользовательского ввода. - **`SEC-04`**: Проверка `allowCleartext` для `authUrl` до открытия браузера. - **`SEC-05`**: Тикет передается в заголовке `Authorization: Bearer `, предотвращая утечки в URL. - **`SEC-07`, `NET-08`, `SEC-08`**: Обработка сбоев инициализации `EncryptedTokenVault`, запись через `.commit()`, типизированный `HermesHttpException`, удаление поиска подстроки «401», `FLAG_SECURE` на время показа секретных полей. - **`SEC-06`**: Синхронизация контекста строго ограничена скользящим окном из 10 сообщений, передаётся отдельным параметром `context_preamble` с глубокой санитизацией секретов. ### 3. Список UNVERIFIED - `Проверка отпечатка самоподписанного сертификата и FLAG_SECURE на физическом устройстве`: **UNVERIFIED** (в headless CI окружении нет подключенного Android-устройства). ### 4. Итоговый статус **ACCEPTED**. Задание 06 выполнено.