Skip to content

Commit 901e8fd

Browse files
malysclaude
andcommitted
refactor: rename MG4Control to EVProfile and split release channels
Rename the app and its package (com.mg4.control -> com.evsuite.profile) as part of the suite-wide move away from the vehicle-specific MG4 prefix, and point the vendored library at the consolidated EVHardware. Release channels replace the historical distribution flavors: stable is offline and manually updated, unstable is a co-installable rolling pre-release carrying the updater and the network permission. Updater code and its tests now live only in the unstable source sets, so stable builds cannot ship them. VehicleWriteGateTest follows EVHardware's hardened gate: the caller threshold and the park rescue are gone, so the test now covers standstill, movement and unreadable speed through decide(speed) alone. Note for release notes: the application ID changes, so an existing install is not upgraded in place. The new build installs alongside the old one and does not inherit its profiles or permissions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent cb401e0 commit 901e8fd

123 files changed

Lines changed: 1909 additions & 2099 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/CONTRIBUTING.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Contributing
22

3-
Thank you for your interest in contributing to MG4Control! This guide explains how to report issues, suggest features, and submit code contributions—with optional support from Claude AI to improve your submissions.
3+
Thank you for your interest in contributing to EVProfile! This guide explains how to report issues, suggest features, and submit code contributions—with optional support from Claude AI to improve your submissions.
44

55
## Table of Contents
66

@@ -49,7 +49,7 @@ Claude AI can help you:
4949

5050
1. **Start a conversation** with Claude:
5151
```
52-
I need to report a bug in MG4Control. Help me write a clear issue report.
52+
I need to report a bug in EVProfile. Help me write a clear issue report.
5353
5454
[Paste your reproduction steps, error messages, and environment details]
5555
```
@@ -94,7 +94,7 @@ Claude can help you:
9494

9595
1. **Start a conversation** with Claude:
9696
```
97-
I want to suggest a new feature for MG4Control to [describe problem].
97+
I want to suggest a new feature for EVProfile to [describe problem].
9898
9999
[Provide your initial idea, use case, and any constraints]
100100

‎.github/FUNDING.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ liberapay: # Replace with a single Liberapay username
1010
issuehunt: # Replace with a single IssueHunt username
1111
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
1212
polar: # Replace with a single Polar username
13-
buy_me_a_coffee: slideen
13+
buy_me_a_coffee:
1414
thanks_dev: # Replace with a single thanks.dev username
15-
custom: ['https://www.paypal.com/paypalme/pfauquembergue']
15+
custom: []

‎.github/ISSUE_TEMPLATE/bug_report.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ body:
6161
label: "Steps to Reproduce"
6262
description: "Exact steps to reproduce the bug"
6363
placeholder: |
64-
1. Open MG4Control
64+
1. Open EVProfile
6565
2. Set vehicle speed to 50 km/h
6666
3. Tap "Drive Profile" → "Sport Mode"
6767
4. Observe crash

‎.github/ISSUE_TEMPLATE/config.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ contact_links:
33
- name: Security vulnerability
44
url: ../../security/advisories/new
55
about: Report privately, never in a public issue.
6-
- name: MG4Hardware (the shared vehicle-access library)
7-
url: https://github.com/malys/MG4Hardware
6+
- name: EVHardware (the shared vehicle-access library)
7+
url: https://github.com/malys/EVHardware
88
about: Signal IDs, CarPropertyManager access and vendor-service plumbing belong there.

‎.github/ISSUE_TEMPLATE/feature_request.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ body:
1212
1313
Have an idea to make this project better? We'd love to hear it!
1414
15-
**Before requesting:** Please check if a similar feature has been requested in [Discussions](https://github.com/malys/MG4Control/discussions).
15+
**Before requesting:** Please check if a similar feature has been requested in [Discussions](https://github.com/malys/EVProfile/discussions).
1616
1717
- type: checkboxes
1818
id: checks

‎.github/ISSUE_TEMPLATE/security.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ body:
8282
attributes:
8383
label: "Affected Projects & Versions"
8484
description: "Which projects and versions are affected?"
85-
placeholder: "MG4Control < 1.2.0 (all builds), MG4Hardware < 0.5.0"
85+
placeholder: "EVProfile < 1.2.0 (all builds), EVHardware < 0.5.0"
8686
validations:
8787
required: true
8888

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
root="$(cd "$(dirname "$0")/../.." && pwd)"
5+
stable_manifest="$(find "$root/app/build/intermediates" -path '*stableDebug*' -name AndroidManifest.xml | head -1)"
6+
unstable_manifest="$(find "$root/app/build/intermediates" -path '*unstableDebug*' -name AndroidManifest.xml | head -1)"
7+
8+
if [ -z "$stable_manifest" ] || [ -z "$unstable_manifest" ]; then
9+
echo "::error::Merged channel manifests were not generated."
10+
exit 1
11+
fi
12+
13+
for permission in android.permission.INTERNET android.permission.ACCESS_NETWORK_STATE android.permission.INSTALL_PACKAGES; do
14+
if grep -q "$permission" "$stable_manifest"; then
15+
echo "::error file=$stable_manifest::Stable must not declare $permission"
16+
exit 1
17+
fi
18+
done
19+
20+
for permission in android.permission.INTERNET android.permission.ACCESS_NETWORK_STATE; do
21+
if ! grep -q "$permission" "$unstable_manifest"; then
22+
echo "::error file=$unstable_manifest::Unstable must declare $permission"
23+
exit 1
24+
fi
25+
done
26+
27+
if [ -d "$root/app/src/main/java/com/evsuite/profile/update" ]; then
28+
echo "::error::Updater implementation leaked into the common source set."
29+
exit 1
30+
fi
31+
32+
echo "Channel isolation OK: stable offline/manual, unstable network/OTA."

‎.github/security/permission-allowlist.txt‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Allowed permissions for MG4Control.
1+
# Allowed permissions for EVProfile.
22
# Any uses-permission in a manifest NOT listed here FAILS the CI.
33
# Why: the app runs on a moving vehicle — any new permission
44
# (especially network or vehicle-write) must be reviewed and added here explicitly.
@@ -22,12 +22,11 @@ android.car.permission.CONTROL_CAR_CLIMATE
2222
# Exigée de l'émetteur du broadcast hardkey, en protectionLevel="signature" (T-902) :
2323
# seule une app signée avec la clé plateforme peut l'obtenir. Elle restreint un accès,
2424
# elle n'en accorde pas.
25-
com.mg4.control.permission.RECEIVE_HARDKEY
25+
com.evsuite.profile.permission.RECEIVE_HARDKEY
2626
# External control API: signature-level permission protecting ProfileControlService.
2727
# protectionLevel="signature" → réservée aux apps signées avec la clé plateforme.
28-
# Déclarée ET demandée par MG4Control : demandée pour pouvoir émettre le broadcast.
29-
com.mg4.control.permission.CONTROL_PROFILES
30-
# --- network / auto-update (online variant only) ---
28+
# Déclarée ET demandée par EVProfile : demandée pour pouvoir émettre le broadcast.
29+
com.evsuite.profile.permission.CONTROL_PROFILES
30+
# --- network / OTA (unstable channel only; the merged-manifest gate proves stable lacks it) ---
3131
android.permission.INTERNET
3232
android.permission.ACCESS_NETWORK_STATE
33-
android.permission.INSTALL_PACKAGES

‎.github/workflows/release.yml‎

Lines changed: 36 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
11
name: Release
22

3-
# Build both variants (online + offline) and publish them in the same Release.
4-
# Users choose which APK to install from the GitHub Releases page.
3+
# Stable channel: tagged, offline, and installed manually. workflow_dispatch validates and
4+
# uploads an artifact but deliberately does not publish a GitHub Release.
55
on:
66
push:
7-
tags:
8-
- "v*"
7+
tags: ["v*"]
98
workflow_dispatch:
109

1110
permissions:
1211
contents: write
1312

1413
jobs:
1514
build:
15+
name: Build stable offline APK
1616
runs-on: ubuntu-latest
1717
env:
18-
MG4_KEYSTORE_BASE64: ${{ secrets.MG4_KEYSTORE_BASE64 }}
18+
EV_KEYSTORE_BASE64: ${{ secrets.EV_KEYSTORE_BASE64 }}
1919
steps:
2020
- uses: actions/checkout@v4
2121
with:
2222
submodules: recursive
2323
fetch-depth: 0
24-
ref: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || 'main' }}
2524

2625
- name: Verify release commit belongs to main
2726
if: startsWith(github.ref, 'refs/tags/')
@@ -33,67 +32,55 @@ jobs:
3332
}
3433
3534
- uses: actions/setup-java@v4
36-
with:
37-
distribution: temurin
38-
java-version: "17"
35+
with: { distribution: temurin, java-version: "17" }
36+
- uses: gradle/actions/setup-gradle@v4
3937

40-
- name: Setup Gradle
41-
uses: gradle/actions/setup-gradle@v4
38+
- name: Require platform keystore
39+
run: |
40+
if [ -z "$EV_KEYSTORE_BASE64" ]; then
41+
echo "::error::EV_KEYSTORE_BASE64 is required; refusing to publish an unsigned vehicle APK."
42+
exit 1
43+
fi
4244
4345
- name: Decode platform keystore
44-
if: ${{ env.MG4_KEYSTORE_BASE64 != '' }}
4546
run: |
46-
# Tolerate newlines/spaces in the secret; printf avoids a stray trailing newline.
47-
printf '%s' "$MG4_KEYSTORE_BASE64" | tr -d '[:space:]' | base64 -d > "$RUNNER_TEMP/platform.keystore"
48-
# Validation: a PKCS12/JKS keystore starts with 0x30 (DER SEQUENCE). Otherwise the secret is corrupt.
47+
printf '%s' "$EV_KEYSTORE_BASE64" | tr -d '[:space:]' | base64 -d > "$RUNNER_TEMP/platform.keystore"
4948
if [ "$(head -c1 "$RUNNER_TEMP/platform.keystore" | od -An -tx1 | tr -d ' ')" != "30" ]; then
50-
echo "::error::MG4_KEYSTORE_BASE64 is invalid. Recreate the secret with: base64 -w0 platform.keystore"
49+
echo "::error::EV_KEYSTORE_BASE64 is invalid."
5150
exit 1
5251
fi
53-
echo "MG4_KEYSTORE=$RUNNER_TEMP/platform.keystore" >> "$GITHUB_ENV"
52+
echo "EV_KEYSTORE=$RUNNER_TEMP/platform.keystore" >> "$GITHUB_ENV"
5453
55-
- name: Build online + offline release APKs
54+
- name: Verify and build stable
5655
env:
57-
MG4_KEYSTORE_PASSWORD: ${{ secrets.MG4_KEYSTORE_PASSWORD }}
58-
MG4_KEY_ALIAS: ${{ secrets.MG4_KEY_ALIAS }}
59-
MG4_KEY_PASSWORD: ${{ secrets.MG4_KEY_PASSWORD }}
56+
EV_KEYSTORE_PASSWORD: ${{ secrets.EV_KEYSTORE_PASSWORD }}
57+
EV_KEY_ALIAS: ${{ secrets.EV_KEY_ALIAS }}
58+
EV_KEY_PASSWORD: ${{ secrets.EV_KEY_PASSWORD }}
6059
run: |
6160
chmod +x gradlew
62-
./gradlew assembleOnlineRelease assembleOfflineRelease --no-daemon
61+
bash .github/security/check-permissions.sh
62+
./gradlew testStableDebugUnitTest lintStableDebug processStableDebugMainManifest assembleStableRelease --no-daemon
63+
./gradlew processUnstableDebugMainManifest --no-daemon
64+
bash .github/security/check-channel-isolation.sh
6365
64-
- name: Collect APKs
66+
- name: Collect stable APK
6567
run: |
6668
mkdir -p dist
67-
# AGP 9 emits app-<flavor>-release.apk; rename to the published convention.
68-
for f in $(find app/build/outputs/apk -name "app-*-release.apk"); do
69-
flavor=$(basename "$f" | sed -E 's/app-(.*)-release.apk/\1/')
70-
ver=$(grep -oE 'versionName = "[^"]+"' app/build.gradle.kts | head -1 | sed -E 's/.*"([^"]+)"/\1/')
71-
cp "$f" "dist/MG4Control-${flavor}-${ver}.apk"
72-
done
69+
ver=$(grep -oE 'versionName = "[^"]+"' app/build.gradle.kts | head -1 | sed -E 's/.*"([^"]+)"/\1/')
70+
find app/build/outputs/apk -name "app-stable-release.apk" -exec cp {} "dist/EVProfile-stable-${ver}.apk" \;
7371
ls -la dist/
7472
75-
- name: Upload APKs as workflow artifacts
76-
uses: actions/upload-artifact@v4
77-
with:
78-
name: mg4control-apks
79-
path: dist/*.apk
73+
- uses: actions/upload-artifact@v4
74+
with: { name: evprofile-stable-apk, path: "dist/*.apk" }
8075

81-
- name: Publish to GitHub Release
76+
- name: Publish stable GitHub Release
77+
if: startsWith(github.ref, 'refs/tags/')
8278
uses: softprops/action-gh-release@v2
8379
with:
84-
# Tag push -> stable release on the tag. Manual run -> prerelease "ci-<run>".
85-
tag_name: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || format('ci-{0}', github.run_number) }}
86-
name: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || format('CI build {0}', github.run_number) }}
87-
prerelease: ${{ !startsWith(github.ref, 'refs/tags/') }}
80+
tag_name: ${{ github.ref_name }}
81+
name: ${{ github.ref_name }}
82+
prerelease: false
8883
files: dist/*.apk
8984
body: |
90-
## MG4Control ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || format('ci-{0}', github.run_number) }}
91-
92-
Two variants are provided — **pick one**:
93-
94-
| Variant | File | Network | Auto-update | Target |
95-
|---|---|---|---|---|
96-
| **Online** | `MG4Control-online-*.apk` | yes | yes | standard use |
97-
| **Offline** 🔒 | `MG4Control-offline-*.apk` | none (network perms removed) | no | hardened on-vehicle deployment |
98-
99-
> The offline APK has a distinct applicationId (`com.mg4.control.offline`) and can coexist with the online one.
85+
Stable/offline EVProfile release. This APK contains no updater implementation
86+
and declares no network permission. Installation and updates are manual.

‎.github/workflows/security.yml‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,15 @@ jobs:
2020
- uses: actions/checkout@v4
2121
with:
2222
submodules: recursive
23+
- uses: actions/setup-java@v4
24+
with: { distribution: temurin, java-version: "17" }
25+
- uses: gradle/actions/setup-gradle@v4
2326
- name: Check manifest permissions
24-
run: bash .github/security/check-permissions.sh
27+
run: |
28+
bash .github/security/check-permissions.sh
29+
chmod +x gradlew
30+
./gradlew processStableDebugMainManifest processUnstableDebugMainManifest --no-daemon
31+
bash .github/security/check-channel-isolation.sh
2532
2633
secrets:
2734
name: Secret scan (blocking)
@@ -73,7 +80,7 @@ jobs:
7380
if: always()
7481
run: |
7582
{
76-
echo "# MG4Control security report"
83+
echo "# EVProfile security report"
7784
echo "_$(date -u)_"
7885
echo
7986
echo "## mobsfscan"
@@ -106,7 +113,7 @@ jobs:
106113
if: ${{ env.NVD_API_KEY != '' }}
107114
uses: dependency-check/Dependency-Check_Action@main
108115
with:
109-
project: MG4Control
116+
project: EVProfile
110117
path: "."
111118
format: "SARIF"
112119
args: --nvdApiKey ${{ env.NVD_API_KEY }}

0 commit comments

Comments
 (0)