Skip to content

Подготовить безопасный выпуск 1.8.1 - #1

Merged
Etogerman merged 7 commits into
mainfrom
agent/review-fixes-1-8-1
Aug 3, 2026
Merged

Подготовить безопасный выпуск 1.8.1#1
Etogerman merged 7 commits into
mainfrom
agent/review-fixes-1-8-1

Conversation

@Etogerman

@Etogerman Etogerman commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Что изменено

  • добавлена проверка реальной даты мировых и официальных курсов;
  • сетевые ответы ограничены по размеру, перенаправления разрешены только по HTTPS;
  • XML Банка России защищён от DTD и внешних сущностей с учётом особенностей Android;
  • график учитывает календарные интервалы, показывает пропуски и получил действия TalkBack;
  • кэш истории ограничен 24 наборами, а одна загрузка — 60 секундами;
  • версия обновлена до 1.8.1, targetSdk и compileSdk — до API 36;
  • обновлены совместимые AndroidX-зависимости, AGP и Gradle Wrapper с контрольной суммой;
  • добавлены Dependabot, правовые сведения и инструкция проверяемого выпуска.

Исправления по независимому ревью

  1. APK и таблица деобфускации сохраняются разными артефактами; перед аттестацией CI явно проверяет ожидаемый путь APK.
  2. Тайм-аут истории преобразуется в обычную ошибку загрузки, поэтому приложение возвращает сохранённый график; блокирующие HTTPS-запросы теперь участвуют в отмене корутины.
  3. Резервный адрес используется также после ответа HTTP 200 с некорректными или устаревшими данными — проверка содержимого выполняется отдельно для каждого источника.
  4. В режиме Банка России статус свежести учитывает мировой резерв для валют, которых нет в официальном наборе.
  5. Последний открытый экран сохраняется в настройках приложения и восстанавливается после холодного запуска.

Добавлены регрессионные тесты для резервных источников, отмены, тайм-аута, объединённого статуса курса и сохранения экрана.

Безопасность и выпуск

Ключ подписи остаётся только у владельца и не передаётся в GitHub Actions. Для тегов CI формирует неподписанный APK и аттестацию происхождения; локальная подпись, сертификат, SHA-256 и неизменяемый GitHub Release проверяются по RELEASING.md.

История main и ветки PR точечно переписана: личный e-mail удалён из достижимых веток, тегов и PR-ссылок. Старый недостижимый объект может оставаться в серверном кэше GitHub до отдельной очистки через GitHub Support.

Тег и выпуск 1.8.1 будут созданы отдельно после слияния.

Локальные проверки

  • ./gradlew --no-daemon testDebugUnitTest testReleaseUnitTest lintRelease assembleRelease;
  • 45 debug- и 45 release-unit-тестов: 0 сбоев;
  • ./gradlew --no-daemon connectedDebugAndroidTest;
  • 3 инструментальных теста на Android 15: 0 сбоев;
  • lint: 0 ошибок, 4 информационные рекомендации о более новых версиях AndroidX;
  • git diff --check: замечаний нет.

Результат ревью

  • Claude проверил итоговые изменения и не нашёл требующих исправления проблем;
  • Copilot оставил три inline-треда;
  • русская строка о пропущенных датах исправлена и покрыта регрессионным тестом;
  • семантика сводного времени проверки явно задокументирована и закреплена тестом;
  • замечание к gradlew проверено по официальному шаблону и JAR Gradle 8.14.5 и признано ложным срабатыванием;
  • по каждому треду опубликован отдельный русскоязычный ответ;
  • все три review-треда закрыты после успешного повторного CI.

GitHub Actions

Успешный прогон коммита cbe49fc: https://github.com/Etogerman/clean-rate-android/actions/runs/30752358971

  • «Тесты, анализ и сборка» — успешно;
  • «Проверка на Android 15» — успешно, 3 из 3 тестов;
  • APK и таблица деобфускации сохранены отдельными артефактами;
  • в скачанном APK-артефакте подтверждён корневой путь app-release-unsigned.apk;
  • SHA-256 неподписанного APK: a34175d10b6121173a2db9cfc43aae6750647d6c4667efb6c528a9e1be83a2e7;
  • проверка ZIP-структуры APK ошибок не обнаружила;
  • задача аттестации ожидаемо пропущена для PR и запускается только для тега v*.

@Etogerman
Etogerman requested a review from Copilot August 2, 2026 14:10
@Etogerman

Copy link
Copy Markdown
Owner Author

@claude[agent] review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

PR готовит «безопасный» релиз 1.8.1: усиливает проверку свежести данных, ограничивает сетевые ответы/редиректы, повышает устойчивость к ошибкам источников и добавляет проверяемую процедуру выпуска/CI-аттестации.

Changes:

  • Усилена безопасность и устойчивость загрузок: лимиты размера ответов, HTTPS-only редиректы, защита XML ЦБ от DTD/внешних сущностей, тайм-аут истории и fallback-логика по валидности данных.
  • Улучшена UX/доступность графика: календарная шкала, явное отображение пропусков, TalkBack actions, сохранение последнего экрана.
  • Обновлены версии/инфраструктура: API 36, Gradle/AGP, CI с артефактами и provenance для тегов, Dependabot, обновлены документы релиза и правовые уведомления.

Reviewed changes

Copilot reviewed 42 out of 44 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
THIRD_PARTY.md Расширены сведения о сторонних компонентах и происхождении звука.
SECURITY.md Обновлены инструкции по приватному репорту уязвимостей и проверке APK/сертификата.
RELEASING.md Добавлена процедура проверяемого выпуска (CI→артефакт→аттестация→локальная подпись→Release).
RELEASE_NOTES_1.8.1.md Добавлены заметки выпуска 1.8.1.
README.md Обновлены инструкции установки/сборки и отпечаток сертификата подписи.
gradlew.bat Изменён способ запуска wrapper’а через -jar.
gradlew Обновлён shell wrapper, включая запуск через -jar.
gradle/wrapper/gradle-wrapper.properties Обновлён Gradle и добавлена SHA-256 контрольная сумма дистрибутива.
CONTRIBUTING.md Обновлены локальные команды проверки (добавлен assembleRelease).
CHANGELOG.md Добавлен раздел 1.8.1 и перечисление изменений.
build.gradle.kts Обновлён Android Gradle Plugin.
app/src/test/java/ru/abrikosov/cleanrate/ui/UiLocalizationTest.kt Адаптированы тесты выбора точки графика под календарную шкалу.
app/src/test/java/ru/abrikosov/cleanrate/ui/RateStatusPolicyTest.kt Добавлены тесты объединённого статуса свежести/seed для режима ЦБ.
app/src/test/java/ru/abrikosov/cleanrate/data/SourceResilienceTest.kt Тесты fallback-источников, отмены и тайм-аута истории.
app/src/test/java/ru/abrikosov/cleanrate/data/RateFreshnessPolicyTest.kt Тесты политики «реальной» свежести даты курса.
app/src/test/java/ru/abrikosov/cleanrate/data/MarketRateParserTest.kt Тесты отклонения устаревших/будущих live-данных.
app/src/test/java/ru/abrikosov/cleanrate/data/HttpsClientTest.kt Тесты лимитированного чтения ответа.
app/src/test/java/ru/abrikosov/cleanrate/data/HistoryCachePolicyTest.kt Тесты политики вытеснения записей кэша истории.
app/src/test/java/ru/abrikosov/cleanrate/data/CbrXmlParserTest.kt Тесты защиты XML (doctype/entities, лимит размера, UTF-16).
app/src/main/java/ru/abrikosov/cleanrate/ui/UiText.kt Добавлены тексты для статусов устаревания и доступности графика/пропусков.
app/src/main/java/ru/abrikosov/cleanrate/ui/RateStatusPolicy.kt Введена политика объединения статусов свежести/seed для разных источников.
app/src/main/java/ru/abrikosov/cleanrate/ui/RateChartScreen.kt Календарная шкала графика, показ пропусков, TalkBack actions, новые алгоритмы выбора точек.
app/src/main/java/ru/abrikosov/cleanrate/ui/HistoryViewModel.kt Проброшен missingPointCount в UI-состояние истории.
app/src/main/java/ru/abrikosov/cleanrate/ui/ConverterViewModel.kt Параллельное обновление источников, сохранение/восстановление видимости графика.
app/src/main/java/ru/abrikosov/cleanrate/ui/ConverterScreen.kt Использование объединённого статуса свежести/seed и новое отображение stale-состояния.
app/src/main/java/ru/abrikosov/cleanrate/MainActivity.kt Сохранение последнего экрана через состояние ViewModel/репозитория.
app/src/main/java/ru/abrikosov/cleanrate/data/SourceFallback.kt Общая функция перебора источников до первого валидного.
app/src/main/java/ru/abrikosov/cleanrate/data/RateFreshnessPolicy.kt Новая политика свежести по дате данных (окна возраст/будущее).
app/src/main/java/ru/abrikosov/cleanrate/data/Models.kt Добавлен флаг isStale в снапшоты курсов.
app/src/main/java/ru/abrikosov/cleanrate/data/MarketRateParser.kt Расчёт/проверка isStale и режим requireFresh для live-загрузок.
app/src/main/java/ru/abrikosov/cleanrate/data/HttpsClient.kt Новый HTTPS-клиент: лимиты ответа, HTTPS-only редиректы, cancel-friendly IO.
app/src/main/java/ru/abrikosov/cleanrate/data/HistoryModels.kt Добавлен учёт запрошенного количества точек и вычисление пропусков.
app/src/main/java/ru/abrikosov/cleanrate/data/HistoryCachePolicy.kt Политика вытеснения старых записей кэша истории.
app/src/main/java/ru/abrikosov/cleanrate/data/HistoricalRatesRepository.kt HTTPS-клиент + fallback по валидности, общий тайм-аут, лимит кэша истории.
app/src/main/java/ru/abrikosov/cleanrate/data/CurrencyRepository.kt HTTPS-клиент + fallback по валидности/свежести, сохранение видимости графика.
app/src/main/java/ru/abrikosov/cleanrate/data/CbrXmlParser.kt Усилена безопасность XML-парсинга и добавлен isStale/requireFresh.
app/src/main/java/ru/abrikosov/cleanrate/data/CbrRepository.kt Переход на HTTPS-клиент, лимиты, requireFresh, логирование ошибок.
app/src/main/assets/legal/NOTICE.txt Добавлены правовые уведомления, включаемые в APK.
app/src/androidTest/java/ru/abrikosov/cleanrate/AndroidRuntimeSmokeTest.kt Инструментальные smoke-тесты запуска и Android-рантайм парсинга.
app/proguard-rules.pro Обновлён комментарий/назначение файла правил Proguard.
app/build.gradle.kts Обновлены compileSdk/targetSdk/version, AndroidX зависимости и test deps.
.github/workflows/android.yml CI: сборка release, артефакты APK/mapping, Android 15 tests, provenance для тегов.
.github/dependabot.yml Добавлен Dependabot для Gradle и GitHub Actions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread gradlew
Comment thread app/src/main/java/ru/abrikosov/cleanrate/ui/RateStatusPolicy.kt
Comment thread app/src/main/java/ru/abrikosov/cleanrate/ui/UiText.kt
@Claude

Claude AI commented Aug 2, 2026

Copy link
Copy Markdown

@claude[agent] review

Review completed for commits 678da46..a02cdc7. No changes needed — the code is sound.

Highlights checked:

  • HttpsClient: HTTPS-only with protocol re-check per redirect, redirect cap, declared/streamed size limits, and runInterruptible so blocking requests honour cancellation.
  • CbrXmlParser: layered XXE defence — byte-level <!DOCTYPE/<!ENTITY rejection, throwing EntityResolver, plus best-effort JAXP flags (setFeatureWhenSupported tolerates Android gaps).
  • firstValidSource + repositories: per-source content validation runs even after HTTP 200, CancellationException is rethrown, and the history timeout maps to a normal failure so the cached chart is returned.
  • RateFreshnessPolicy/RateStatusPolicy: data-date freshness with future/past windows; CBR mode merges the world reserve only for currencies absent from the official set — covered by RateStatusPolicyTest.
  • CI: APK and mapping saved as separate artifacts, provenance verifies the expected APK path and is gated to v* tags.

I couldn't run the Gradle suite in this sandbox (Google Maven is blocked, so AGP 8.11.1 fails to resolve), but the green run on a02cdc7 covers it.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • dl.google.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED -Xmx2048m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /home/REDACTED/.gradle/wrapper/dists/gradle-8.14.5-bin/690y85m0j9nfaub7xoiayko8a/gradle-8.14.5/lib/gradle-daemon-main-8.14.5.jar (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@Etogerman
Etogerman marked this pull request as ready for review August 2, 2026 22:33
@Etogerman
Etogerman requested a review from Copilot August 2, 2026 23:18
@Etogerman

Copy link
Copy Markdown
Owner Author

@claude[agent] review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 47 out of 49 changed files in this pull request and generated no new comments.

@Claude

Claude AI commented Aug 2, 2026

Copy link
Copy Markdown

@claude[agent] review

Review completed through d53448b. No changes needed — the code is sound and the latest CI run on d53448b is green.

Verified:

  • HttpsClient: HTTPS-only with per-redirect protocol re-check, redirect cap (3), declared+streamed size limits, and runInterruptible so blocking requests honour cancellation.
  • CbrXmlParser: layered XXE defence — byte-level <!DOCTYPE/<!ENTITY rejection, throwing EntityResolver, plus best-effort JAXP flags via setFeatureWhenSupported (tolerates Android gaps); data-date freshness gated by RateFreshnessPolicy.
  • firstValidSource + HistoricalRatesRepository: per-source content validation runs even after HTTP 200, CancellationException is rethrown, and the 60s history timeout maps to a normal failure so the cached chart is returned.
  • RateStatusPolicy.merge: summary check-time intentionally stays null when any used source lacks a time, documented and covered by tests.
  • RefreshCoordinator: pending refresh replans against the current source after completion.
  • Screen/session restore in ConverterViewModel and history selection persistence look correct.

I couldn't run the Gradle suite here (Google Maven is blocked, so AGP fails to resolve), but the green run on d53448b covers it.

@Etogerman
Etogerman merged commit 1fc2d78 into main Aug 3, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants