From fb2a3763fd3fbdd866dfcfe97ea77a4bc2b50d9c Mon Sep 17 00:00:00 2001 From: Maxim Kramarenko Date: Wed, 12 Aug 2026 13:43:54 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B0=D0=B9=D0=BB=D1=8B=20=D1=81=D0=BE?= =?UTF-8?q?=D0=BE=D0=B1=D1=89=D0=B5=D1=81=D1=82=D0=B2=D0=B0,=20=D1=88?= =?UTF-8?q?=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=D1=8B,=20dependabot,=20NOTICE=20?= =?UTF-8?q?=D0=B8=20workflow=20=D1=80=D0=B5=D0=BB=D0=B8=D0=B7=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Метрика community profile была 42%: присутствовали только README, LICENSE и description. Добавлено: - SECURITY.md — приватный канал через GitHub Security Advisories. Отдельно оговорено, что вне области: слабости самого протокола EPC Gen2 (тег по стандарту читается и пишется любым ридером в радиусе) и внутренности проприетарного SDK Chainway - CONTRIBUTING.md — сборка, роль JDK 17 против jvmTarget 11, описание существующих юнит-тестов, требование держать вызовы железа за адаптерами, перечень поведения, которое проверяется только на C5 - CODE_OF_CONDUCT.md — Contributor Covenant 2.1 - NOTICE — правовой статус app/libs/DeviceAPI_ver20230301_release.aar. Проприетарный бинарник вендора лежал в репозитории под Apache-2.0 без единого пояснения, откуда он и на каких условиях распространяется - шаблоны issue и pull request. Шаблон бага требует модель устройства, версию Android и раздел приложения; шаблон PR спрашивает, проверялось ли изменение на реальном железе - .github/dependabot.yml — gradle и github-actions ежемесячно, с группировкой обновлений - .github/workflows/release.yml — по пушу тега v* прогоняет юнит-тесты, собирает APK и создает GitHub Release Про APK в релизе: приложение уже распространяется через RuStore, и описание релиза ведет туда как на основной способ установки. Приложенный APK помечен как -debug и снабжен предупреждением, что его подпись не совпадает с магазинной и поверх установленной версии он не встанет. В конце workflow — инструкция, как перейти на подписанную сборку тем же ключом, что и в RuStore. README: у пункта про SDK появилась ссылка на NOTICE. Синтаксис всех YAML проверен парсером. Co-Authored-By: Claude Opus 5 --- .github/ISSUE_TEMPLATE/bug_report.yml | 83 ++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 8 ++ .github/ISSUE_TEMPLATE/feature_request.yml | 39 ++++++++ .github/dependabot.yml | 31 ++++++ .github/pull_request_template.md | 31 ++++++ .github/workflows/release.yml | 107 +++++++++++++++++++++ CODE_OF_CONDUCT.md | 75 +++++++++++++++ CONTRIBUTING.md | 72 ++++++++++++++ NOTICE | 39 ++++++++ README.md | 2 +- SECURITY.md | 45 +++++++++ 11 files changed, 531 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/release.yml create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 NOTICE create mode 100644 SECURITY.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..497a684 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,83 @@ +name: Bug report +description: Something does not work as expected +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for reporting. Precise reproduction steps make fixes much faster. + + **Found a security issue?** Do not describe it here — use the [private form](https://github.com/maximkr/rfid-manager/security/advisories/new), see [SECURITY.md](https://github.com/maximkr/rfid-manager/blob/main/SECURITY.md). + + - type: textarea + id: what-happened + attributes: + label: What happens + description: Describe the problem and what you expected instead. + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to reproduce + placeholder: | + 1. Open the ... screen + 2. Set write power to ... dBm + 3. Pull the trigger + 4. ... + validations: + required: true + + - type: input + id: device + attributes: + label: Device + description: Handheld model and Android version. + placeholder: "Chainway C5, Android 13" + validations: + required: true + + - type: input + id: version + attributes: + label: App version + description: From the release page, or `versionName` if you built it yourself. + placeholder: "1.0" + validations: + required: true + + - type: dropdown + id: area + attributes: + label: Which part + options: + - Scan & Write (tag programming) + - Radar (tag search) + - Barcode scanner + - Activity log + - Settings + - Reader connection / startup + - Other + validations: + required: true + + - type: input + id: tags + attributes: + label: Tags used + description: Tag type and EPC size, if relevant. + placeholder: "EPC Gen2, 6-word EPC" + + - type: textarea + id: logs + attributes: + label: Logs + description: Relevant output from the in-app Activity Log, or `adb logcat`. + render: text + + - type: textarea + id: extra + attributes: + label: Anything else + description: Screenshots, workarounds, anything that helps. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..4fd1545 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Report a vulnerability + url: https://github.com/maximkr/rfid-manager/security/advisories/new + about: Private channel. Please do not describe security issues in public issues. + - name: Chainway device SDK + url: https://www.chainway.net/ + about: Problems inside the vendor DeviceAPI SDK need to go to Chainway, not here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..8b8341f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,39 @@ +name: Feature request +description: An idea for a new capability or an improvement +labels: ["enhancement"] +body: + - type: textarea + id: problem + attributes: + label: What problem does this solve + description: Describe the situation that is awkward today — what you are trying to do and why it does not work. + validations: + required: true + + - type: textarea + id: solution + attributes: + label: How it could work + description: Your proposal. If it involves the UI, describe it or attach a sketch. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: What you do instead today + description: Workarounds, other apps, manual steps. + + - type: input + id: device + attributes: + label: Device + description: Which handheld you use, if the request is hardware-specific. + placeholder: "Chainway C5" + + - type: checkboxes + id: contribution + attributes: + label: Contribution + options: + - label: I am willing to implement this myself diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..69edd2e --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,31 @@ +version: 2 + +updates: + # AndroidX, Kotlin, AGP и прочее из gradle/libs.versions.toml + - package-ecosystem: gradle + directory: "/" + schedule: + interval: monthly + open-pull-requests-limit: 5 + groups: + androidx: + patterns: + - "androidx.*" + kotlin: + patterns: + - "org.jetbrains.kotlin*" + - "org.jetbrains.kotlinx:*" + minor-and-patch: + update-types: + - minor + - patch + + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: monthly + open-pull-requests-limit: 5 + groups: + actions: + patterns: + - "*" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..ea5cd90 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,31 @@ + + +## What changes + + + +## Related issues + + + +## How to verify + + + +## Tested on hardware? + + + +- [ ] Verified on a physical device +- [ ] Not applicable — change does not touch reader, scanner or radar behaviour + +## Screenshots + + + +## Checklist + +- [ ] `./gradlew testDebugUnitTest assembleDebug` passes locally +- [ ] New logic is covered by unit tests, or there is a reason it cannot be +- [ ] Hardware calls stay behind the adapter interfaces, not inlined into fragments +- [ ] Documentation updated — `README.md`, `AGENTS.md` (or not needed) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..45063bd --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,107 @@ +name: Release + +# Запускается при пуше тега вида v1.1.0 +# git tag v1.1.0 && git push origin v1.1.0 +on: + push: + tags: + - 'v*' + +permissions: + contents: write # создать GitHub Release + +jobs: + release: + name: APK + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '17' + + - name: Set up Android SDK + uses: android-actions/setup-android@v3 + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@v4 + + # Релиз не выпускается, если юнит-тесты красные + - name: Unit tests + run: ./gradlew --no-daemon testDebugUnitTest + + # Собирается debug-сборка: она подписана отладочным ключом и потому + # устанавливается на устройство сразу. Чтобы выпускать release-сборку, + # нужен keystore — см. комментарий в конце файла. + - name: Build APK + run: ./gradlew --no-daemon assembleDebug + + - name: Подготовить артефакт + run: | + mkdir -p dist + cp app/build/outputs/apk/debug/app-debug.apk \ + "dist/rfid-manager-${GITHUB_REF_NAME}-debug.apk" + + - name: Подготовить описание релиза + run: | + cat > release-notes.md <<'EOF' + ## Установка + + **Обычный способ — [RuStore](https://www.rustore.ru/catalog/app/com.trackstudio.rfidmanager).** + Оттуда приходит официальная подписанная сборка, она же обновляется штатно. + + Приложенный ниже `rfid-manager-TAG_PLACEHOLDER-debug.apk` — сборка для + тестирования и сайдлоада: собрана из исходников этого тега и подписана + отладочным ключом. + + ```bash + adb install -r rfid-manager-TAG_PLACEHOLDER-debug.apk + ``` + + > ⚠️ Отладочный ключ не совпадает с ключом сборки из RuStore. Поставить + > этот APK поверх версии из магазина не получится — Android откажет + > из-за несовпадения подписи. Сначала удалите установленное приложение. + > Обратная замена тоже потребует удаления. + + Требуется Android 13 (API 33) или новее. Разрабатывалось и проверялось + на **Chainway C5**. + EOF + sed -i "s/TAG_PLACEHOLDER/${GITHUB_REF_NAME}/g" release-notes.md + + - name: Create GitHub Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "${GITHUB_REF_NAME}" \ + "dist/rfid-manager-${GITHUB_REF_NAME}-debug.apk" \ + --title "${GITHUB_REF_NAME}" \ + --notes-file release-notes.md \ + --generate-notes + +# ---------------------------------------------------------------------------- +# Как перейти на подписанную release-сборку +# +# 1. Создать keystore: +# keytool -genkey -v -keystore release.jks -keyalg RSA -keysize 2048 \ +# -validity 10000 -alias release +# 2. Добавить в Settings -> Secrets and variables -> Actions секреты: +# KEYSTORE_BASE64 — base64 файла release.jks +# KEYSTORE_PASSWORD +# KEY_ALIAS +# KEY_PASSWORD +# 3. Прописать signingConfigs в app/build.gradle.kts, читая их из переменных +# окружения, и заменить выше assembleDebug на assembleRelease, а путь — +# на app/build/outputs/apk/release/app-release.apk +# +# Использовать здесь тот же keystore, которым подписана сборка в RuStore, — +# тогда APK с GitHub будет ставиться поверх магазинной версии без удаления, +# и предупреждение из описания релиза можно будет убрать. +# +# Keystore нужно хранить вне репозитория: потеряв его, вы не сможете выпускать +# обновления, устанавливаемые поверх уже установленной версии. +# ---------------------------------------------------------------------------- diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..fd8db5d --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,75 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official email address, posting via an official social media account, or acting as an appointed representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the maintainer — [@maximkr](https://github.com/maximkr). All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of actions. + +**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved for a specified period of time. Violating these terms may lead to a temporary or permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3c114ab --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,72 @@ +# Contributing to RFID Manager + +Thanks for your interest. This document covers building the project, what to keep in mind when changing it, and how to open a pull request. + +More detailed architecture and style notes live in [`AGENTS.md`](AGENTS.md). + +## Building + +Requires **JDK 17** and the Android SDK. Gradle comes with the wrapper. + +```bash +git clone https://github.com/maximkr/rfid-manager.git +cd rfid-manager + +./gradlew testDebugUnitTest # unit tests +./gradlew assembleDebug # debug APK -> app/build/outputs/apk/debug/ +./gradlew assembleRelease # unsigned release APK +``` + +JDK 17 is what AGP 8.13 runs on. The app module itself targets `jvmTarget = 11` — that is the bytecode level of the app, not the JVM that runs Gradle. + +Install onto a device over ADB: + +```bash +adb install -r app/build/outputs/apk/debug/app-debug.apk +``` + +## About the vendor SDK + +`app/libs/DeviceAPI_ver20230301_release.aar` is Chainway's proprietary device SDK, checked into the repository because it is not published to any Maven repository. It is **not** covered by this project's Apache-2.0 licence — see [NOTICE](NOTICE). + +Everything that talks to the SDK is isolated behind the `UhfReader`, `UhfReaderFactory` and `UhfScannerCleaner` interfaces (declared in `UhfConnectionController.kt`), with the concrete implementations in `ChainwayUhfAdapters.kt`. That is why the connection logic can be unit-tested without a device. Please keep it that way: new hardware calls belong behind an adapter, not scattered through fragments. + +## Testing + +The project has real JVM unit tests in `app/src/test/`, and they run on every pull request: + +- `EpcTargetNormalizerTest` — EPC normalisation, non-hex rejection, padding for 6- and 8-word EPCs +- `RadarPowerWindowControllerTest` — radar power window logic +- `UhfConnectionControllerTest` — reader init ordering, freeing the old reader, retry with backoff +- `BarcodeSoundPolicyTest` — suppressing vendor scanner sounds + +```bash +./gradlew testDebugUnitTest +``` + +New logic should come with tests. If something cannot be tested without hardware, that is usually a hint it should be split — pull the decision-making into a plain class and keep the device call behind an adapter, as the existing controllers do. + +Instrumented tests in `app/src/androidTest/` require a device or emulator and are not run in CI. + +## Testing on hardware + +Behaviour that genuinely needs a C5 in hand: + +- writing to tags at various power levels (5–30 dBm) — especially that neighbouring tags are not overwritten; +- physical trigger button handling; +- radar behaviour as you approach a target, including audio feedback; +- barcode scanner integration and sound suppression. + +If your change touches any of these, say in the pull request whether you verified it on a device, and on which one. + +## Pull requests + +1. Branch from `main`, name it meaningfully: `fix/...`, `feature/...`, `docs/...`. +2. Make sure `./gradlew testDebugUnitTest assembleDebug` passes locally. +3. Describe what changes and why. For UI changes, attach before/after screenshots. +4. Wait for CI to go green. +5. One pull request — one logical change. + +## Licence + +By submitting a pull request you agree that your contribution is licensed under the [Apache License 2.0](LICENSE). diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..9276e39 --- /dev/null +++ b/NOTICE @@ -0,0 +1,39 @@ +RFID Manager +Copyright 2025 Maxim Kr and contributors + +This product is licensed under the Apache License, Version 2.0. +See the LICENSE file for the full licence text. + +-------------------------------------------------------------------------- +Third-party components +-------------------------------------------------------------------------- + +app/libs/DeviceAPI_ver20230301_release.aar + + Chainway DeviceAPI SDK (UHF RFID and barcode scanner) + Copyright Shenzhen Chainway Information Technology Co., Ltd. + + This is a proprietary binary distributed by the device vendor for use + with Chainway handheld terminals. It is NOT covered by the Apache + License 2.0 that applies to the rest of this repository, and no + licence is granted to it by this project. + + The file is committed to this repository because the vendor does not + publish it to any Maven repository, and the application cannot be + built without it. It is redistributed here on the understanding that + Chainway supplies it to users of its hardware for exactly this + purpose. + + If you intend to use this application commercially, or to redistribute + it, obtain the SDK and its licence terms directly from Chainway: + https://www.chainway.net/ + + If you are a rights holder and consider this redistribution improper, + please open an issue or contact the maintainer and it will be removed. + +-------------------------------------------------------------------------- + +Other dependencies are resolved from Maven Central and Google's Maven +repository at build time and are not redistributed in this repository. +Their licences are those declared by their respective projects; see +gradle/libs.versions.toml and app/build.gradle.kts for the full list. diff --git a/README.md b/README.md index f593b00..8676308 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ An innovative tool for pinpointing a specific tag among hundreds of others, util ## Technical Details * **Language**: Kotlin 2.1.0 + Coroutines (for asynchronous, non-blocking hardware communication). * **Architecture**: Single Activity + Jetpack Navigation Component + Shared ViewModel. -* **SDK**: Chainway DeviceAPI (UHF + Barcode). +* **SDK**: Chainway DeviceAPI (UHF + Barcode). Proprietary vendor binary bundled in `app/libs/` — not covered by this project's Apache-2.0 licence, see [NOTICE](NOTICE). * **UI**: Modern Material 3 interface featuring a clean, green color palette. ## How to Build & Run diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..9a2db92 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,45 @@ +# Security Policy + +## Supported Versions + +This project is developed against **Chainway C5** and compatible UHF RFID handhelds. Only the latest release on `main` receives fixes. + +## Reporting a Vulnerability + +**Please do not open a public issue for security problems.** + +Use GitHub's private channel instead: [**Security → Report a vulnerability**](https://github.com/maximkr/rfid-manager/security/advisories/new). Reports there are visible only to the maintainers. + +If the private form is unavailable, contact the maintainer — [@maximkr](https://github.com/maximkr). + +### What to include + +- app version (from the release page or `versionName` in `app/build.gradle.kts`); +- device model and Android version; +- steps to reproduce; +- what an attacker gains; +- whether physical access to the device or proximity to the RFID reader is required. + +### Response times + +- **acknowledgement** — within 5 business days; +- **initial assessment** — within 14 days; +- fix and advisory — by agreement, depending on severity. + +Please keep details private until a fix is released. + +## Scope + +Relevant areas for this app: + +- unintended tag writes — in particular anything that could overwrite EPC memory of neighbouring tags; +- handling of scanned barcode data before it reaches the tag; +- exported Android components (activities, services, receivers) reachable by other apps on the device; +- permission and intent handling; +- data written to logs or exported files. + +## Out of scope + +- **RFID protocol weaknesses themselves.** EPC Gen2 tags are, by design, readable and often writable by anyone with a reader in range. This is a property of the standard, not a defect in this app. +- **Vendor SDK internals.** `app/libs/DeviceAPI_ver20230301_release.aar` is a proprietary binary supplied by Chainway. Issues inside it must be reported to the vendor; we can only work around them. +- **Physical access attacks** on an unlocked device.