diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ce24bae..73d6815 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,28 +7,8 @@ concurrency: on: push: branches: [ main ] - paths: - - 'app/**' - - 'gradle/**' - - 'gradlew' - - 'gradlew.bat' - - 'build.gradle.kts' - - 'settings.gradle.kts' - - 'gradle.properties' - - 'scripts/**' - - '.github/workflows/ci.yml' pull_request: branches: [ main ] - paths: - - 'app/**' - - 'gradle/**' - - 'gradlew' - - 'gradlew.bat' - - 'build.gradle.kts' - - 'settings.gradle.kts' - - 'gradle.properties' - - 'scripts/**' - - '.github/workflows/ci.yml' workflow_dispatch: jobs: @@ -70,32 +50,61 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + fetch-depth: 0 + + - name: Detect Android changes + id: changes + shell: bash + run: | + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + base="${{ github.event.pull_request.base.sha }}" + else + base="${{ github.event.before }}" + fi + if git diff --name-only "$base" "${{ github.sha }}" | grep -Eq '^(app/|gradle/|scripts/|gradlew$|gradlew\.bat$|build\.gradle\.kts$|settings\.gradle\.kts$|gradle\.properties$)'; then + echo "android=true" >> "$GITHUB_OUTPUT" + else + echo "android=false" >> "$GITHUB_OUTPUT" + fi + + - name: Confirm documentation-only change + if: steps.changes.outputs.android != 'true' + run: echo "No Android or build inputs changed; required check passes without Gradle." - name: Set up JDK 17 + if: steps.changes.outputs.android == 'true' uses: actions/setup-java@cf277c60eb25467037889841efdb72551f06f6c3 # v4 with: distribution: 'temurin' java-version: '17' - name: Setup Gradle + if: steps.changes.outputs.android == 'true' uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3 - name: Grant execute permission for gradlew + if: steps.changes.outputs.android == 'true' run: chmod +x gradlew - name: Run unit tests + if: steps.changes.outputs.android == 'true' run: ./gradlew testDebugUnitTest --no-daemon - name: Run Android lint + if: steps.changes.outputs.android == 'true' run: ./gradlew lint --no-daemon - name: Assemble Debug APK + if: steps.changes.outputs.android == 'true' run: ./gradlew assembleDebug --no-daemon - name: Validate Release APK + if: steps.changes.outputs.android == 'true' run: ./gradlew assembleRelease -PreleaseSigningRequired=false --no-daemon - name: Upload Debug APK + if: steps.changes.outputs.android == 'true' uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: flowpilot-debug-apk diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e5b034..95bad44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,26 @@ All notable FlowPilot changes are documented here. +## [Unreleased] + +Changes completed after `1.0.2` and intended for the next release. + +### Added + +- Safe rule duplication from the Home list: creates a disabled, immediately editable copy with a new identity and reset runtime state. Webhook secrets are decrypted and re-encrypted with fresh Android Keystore ciphertext; TTS cache files are copied independently with failure-safe cleanup. +- Non-blocking conflict warnings before saving or enabling automations: detects opposing state actions with likely/possible confidence, links to the conflicting rule for inspection, preserves the pending operation across inspection, and requires a deliberate override. Trigger overlap follows runtime wildcard semantics without exposing notification keywords or other sensitive arguments. + +### Security + +- Enabled Dependabot vulnerability alerts and security update pull requests. +- Enabled secret scanning, push protection, and private vulnerability reporting for the public repository. +- Protected `main`: pull requests, a current successful `Build & Test` check, and resolved review conversations are required; force-push and branch deletion are disabled. + +### Verification + +- GitHub `Build & Test` passed after both feature branches were reconciled on `main`. +- Android instrumentation remains a manual emulator gate; physical-device validation for these two features is still pending. + ## [1.0.2] - 2026-09-13 ### Added diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 956e064..ada5c55 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,6 +44,8 @@ cd flowpilot 4. **Conventional Commits:** Use clear commit messages (e.g., `feat: add screen brightness action`, `fix: prevent duplicate bluetooth broadcast`). 5. **Open a PR:** Describe the change, the problem it solves, and how you tested it on device. +For suspected security vulnerabilities, follow [SECURITY.md](SECURITY.md) and use private vulnerability reporting instead of a public issue. + --- ## Localization / Translations diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..6c51ef2 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,29 @@ +# Security Policy + +## Supported versions + +Security fixes target the latest release and the current `main` branch. + +## Reporting a vulnerability + +Please do not open a public issue for suspected security vulnerabilities. + +Use GitHub's private vulnerability reporting: + +1. Open the repository's **Security** tab. +2. Select **Advisories**. +3. Select **Report a vulnerability**. + +Include affected version or commit, reproduction steps, expected impact, and any suggested mitigation. Do not include real user secrets, credentials, phone numbers, webhook payloads, or other private data. + +The maintainer will review the report privately and coordinate validation, remediation, and disclosure through a GitHub Security Advisory when appropriate. + +## Scope + +High-priority reports include: + +- Exposure of webhook credentials, backup passwords, phone numbers, SMS content, or location data +- Authentication, authorization, Android Keystore, backup, or import-validation bypasses +- Unsafe privileged command execution through Shizuku +- Unintended network transmission, telemetry, or persistent sensitive logging +- Dependency or build-pipeline compromise diff --git a/docs/STATUS.md b/docs/STATUS.md index ddf607e..82cd9d5 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -11,7 +11,7 @@ Last updated: 2026-09-14 - Action reordering, live location fetcher, Automation Presets, and Geofencing unit tests (`AutomationRepositoryGeofenceQueueTest`, `GeofenceConfigValidationTest`, `GeofenceDiffTest`, `GeofencePrerequisitesTest`, `LocationDependencyTest`, `RuleEvaluatorGeofenceTest`) implemented and verified. - Encrypted backup unit coverage verifies full-secret round trips, enabled-state preservation, plaintext non-leakage, wrong-password/tamper rejection, format/version/KDF bounds, single-rule backup, normal-export regression, and cross-device Android Keystore re-encryption. - History localization unit coverage verifies locale-neutral outcome records, masked SMS result arguments, legacy successful outcome mapping, technical failure fallback, and Turkish automatic rule-name generation. -- Conflict analyzer and pre-save/pre-enable warning implemented: exact trigger-target matching, opposing state-action matrix, likely/possible confidence, conflict rule inspection, and deliberate non-blocking override. Kotlin unit/UI tests added; Gradle execution pending parent verification. +- Conflict analyzer and pre-save/pre-enable warning implemented: runtime-aligned trigger overlap, opposing state-action matrix, likely/possible confidence, conflict rule inspection with pending-state restoration, and deliberate non-blocking override. GitHub `Build & Test` passed; physical-device validation remains pending. - GitHub Pages site modularized: split single monolithic `docs/index.html` into external stylesheet (`docs/assets/css/style.css`) and script (`docs/assets/js/app.js`), unified brand favicon (`docs/assets/favicon.svg`), converted brand into accessible home link, compacted desktop footer, and added mobile-first responsive pass (#2, #3). ## Background stability & engine keepalive @@ -41,7 +41,7 @@ Last updated: 2026-09-14 ## Implemented; device validation pending -- Safe rule duplication from the Home list overflow menu: creates a disabled copy with a new UUID/creation time, resets `lastTriggeredAt` and transient registration state, preserves complete configuration, re-encrypts webhook secrets with fresh Android Keystore ciphertext, and opens the copy in Edit immediately. Kotlin unit/build/device verification pending; SDK-free static/resource contracts passed. +- Safe rule duplication from the Home list overflow menu: creates a disabled copy with a new UUID/creation time, resets `lastTriggeredAt` and transient registration state, preserves complete configuration, re-encrypts webhook secrets with fresh Android Keystore ciphertext, and opens the copy in Edit immediately. GitHub unit/build verification and SDK-free static/resource contracts passed; physical-device validation remains pending. - Time Window (`TIME_BETWEEN`) and Days of the Week (`DAYS_OF_WEEK`) conditions (unit tests passed; device smoke tests pending): - Time interval filtering with overnight span support (e.g. 23:00 - 07:00 crossing midnight). - Day of week filtering with Daily, Weekdays, Weekends, and custom day toggles.