Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]

[target.aarch64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ body:
options:
- macOS 13 or later
- x86_64 Linux
- ARM64 Linux
- x86_64 Windows 10/11
- ARM64 Windows 11
validations:
required: true
- type: dropdown
Expand Down
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ body:
options:
- macOS 13 or later
- x86_64 Linux
- ARM64 Linux
- x86_64 Windows 10/11
- ARM64 Windows 11
validations:
required: true
- type: input
Expand Down
29 changes: 25 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,34 @@ jobs:
include:
- name: macOS
runner: macos-15
smoke: false
platform: macos
- name: Linux ARM64
runner: ubuntu-22.04-arm
platform: linux
- name: Windows
runner: windows-2025
smoke: true
platform: windows
- name: Windows ARM64
runner: windows-11-vs2026-arm
platform: windows
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- name: Install Linux application dependencies
if: matrix.platform == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential \
libayatana-appindicator3-dev \
librsvg2-dev \
libssl-dev \
libwebkit2gtk-4.1-dev \
libxdo-dev \
xvfb
- uses: pnpm/action-setup@v6
with:
version: 11.3.0
Expand All @@ -88,7 +106,7 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
shared-key: ci-${{ runner.os }}
shared-key: ci-${{ runner.os }}-${{ runner.arch }}
- run: pnpm install --frozen-lockfile
- name: Build frontend assets
run: pnpm build
Expand All @@ -97,6 +115,9 @@ jobs:
- name: Build desktop application
run: cargo build -p cleanerx-app
- name: Smoke-test Windows application
if: matrix.smoke
if: matrix.platform == 'windows'
shell: pwsh
run: ./scripts/smoke-windows.ps1 -Profile debug
- name: Smoke-test Linux application
if: matrix.platform == 'linux'
run: make smoke-linux LINUX_PROFILE=debug
53 changes: 36 additions & 17 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,27 @@ jobs:
- name: macOS x86_64
os: macos-15-intel
platform: macos
arch: x86_64
arch: x64
target: x86_64-apple-darwin
- name: Linux x86_64
os: ubuntu-22.04
platform: linux
arch: x86_64
arch: x64
target: ""
- name: Linux arm64
os: ubuntu-22.04-arm
platform: linux
arch: arm64
target: ""
- name: Windows x86_64
os: windows-2025
platform: windows
arch: x86_64
arch: x64
target: ""
- name: Windows arm64
os: windows-11-vs2026-arm
platform: windows
arch: arm64
target: ""
runs-on: ${{ matrix.os }}
timeout-minutes: 40
Expand All @@ -126,6 +136,10 @@ jobs:
libxdo-dev \
patchelf \
xvfb
- name: Install GNU Make on Windows ARM64
if: matrix.platform == 'windows' && matrix.arch == 'arm64'
shell: pwsh
run: choco install make --no-progress -y
- uses: pnpm/action-setup@v6
with:
version: 11.3.0
Expand Down Expand Up @@ -225,18 +239,20 @@ jobs:
echo "Expected exactly one macOS app, DMG, updater archive, and updater signature." >&2
exit 1
fi
asset_base="CleanerX-${RELEASE_VERSION}-macos-${RELEASE_ARCH}"
ditto -c -k --keepParent "${app_paths[0]}" \
"release-assets/CleanerX_${RELEASE_VERSION}_macos_${RELEASE_ARCH}_unsigned.app.zip"
"release-assets/${asset_base}.zip"
cp "${dmg_paths[0]}" \
"release-assets/CleanerX_${RELEASE_VERSION}_macos_${RELEASE_ARCH}_unsigned.dmg"
"release-assets/${asset_base}.dmg"
cp "${updater_paths[0]}" \
"release-assets/CleanerX_${RELEASE_VERSION}_macos_${RELEASE_ARCH}_unsigned.app.tar.gz"
"release-assets/${asset_base}.tar.gz"
cp "${updater_signature_paths[0]}" \
"release-assets/CleanerX_${RELEASE_VERSION}_macos_${RELEASE_ARCH}_unsigned.app.tar.gz.sig"
"release-assets/${asset_base}.tar.gz.sig"
- name: Stage Linux release assets
if: matrix.platform == 'linux'
env:
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
RELEASE_ARCH: ${{ matrix.arch }}
run: |
set -euo pipefail
mkdir release-assets
Expand All @@ -248,17 +264,19 @@ jobs:
echo "Expected exactly one deb, AppImage, and AppImage updater signature." >&2
exit 1
fi
asset_base="CleanerX-${RELEASE_VERSION}-linux-${RELEASE_ARCH}"
cp "${deb_paths[0]}" \
"release-assets/CleanerX_${RELEASE_VERSION}_linux_x86_64_unsigned.deb"
"release-assets/${asset_base}.deb"
cp "${appimage_paths[0]}" \
"release-assets/CleanerX_${RELEASE_VERSION}_linux_x86_64_unsigned.AppImage"
"release-assets/${asset_base}.AppImage"
cp "${appimage_signature_paths[0]}" \
"release-assets/CleanerX_${RELEASE_VERSION}_linux_x86_64_unsigned.AppImage.sig"
"release-assets/${asset_base}.AppImage.sig"
- name: Stage Windows release assets
if: matrix.platform == 'windows'
shell: pwsh
env:
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
RELEASE_ARCH: ${{ matrix.arch }}
run: |
New-Item -ItemType Directory -Path release-assets | Out-Null
$msi = @(Get-ChildItem target/release/bundle/msi/*.msi)
Expand All @@ -267,9 +285,10 @@ jobs:
if ($msi.Count -ne 1 -or $nsis.Count -ne 1 -or $nsisSignature.Count -ne 1) {
throw "Expected exactly one MSI, NSIS installer, and NSIS updater signature."
}
Copy-Item $msi[0].FullName "release-assets/CleanerX_$($env:RELEASE_VERSION)_windows_x86_64_unsigned.msi"
Copy-Item $nsis[0].FullName "release-assets/CleanerX_$($env:RELEASE_VERSION)_windows_x86_64_unsigned_setup.exe"
Copy-Item $nsisSignature[0].FullName "release-assets/CleanerX_$($env:RELEASE_VERSION)_windows_x86_64_unsigned_setup.exe.sig"
$assetBase = "CleanerX-$($env:RELEASE_VERSION)-windows-$($env:RELEASE_ARCH)"
Copy-Item $msi[0].FullName "release-assets/$assetBase.msi"
Copy-Item $nsis[0].FullName "release-assets/$assetBase.exe"
Copy-Item $nsisSignature[0].FullName "release-assets/$assetBase.exe.sig"
- name: Record build metadata
shell: bash
env:
Expand All @@ -293,7 +312,7 @@ jobs:
echo "cargo=$(cargo --version)"
echo "node=$(node --version)"
echo "pnpm=$(pnpm --version)"
} > "release-assets/CleanerX_${RELEASE_VERSION}_${RELEASE_PLATFORM}_${RELEASE_ARCH}_build-metadata.txt"
} > "release-assets/CleanerX-${RELEASE_VERSION}-${RELEASE_PLATFORM}-${RELEASE_ARCH}.txt"
- uses: actions/upload-artifact@v7
with:
name: release-${{ matrix.platform }}-${{ matrix.arch }}
Expand Down Expand Up @@ -325,7 +344,7 @@ jobs:
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
run: |
set -euo pipefail
tar -czf "release-assets/CleanerX_${RELEASE_VERSION}_source-lockfiles.tar.gz" \
tar -czf "release-assets/CleanerX-${RELEASE_VERSION}-lockfiles.tar.gz" \
Cargo.lock pnpm-lock.yaml
{
echo "tag=$GITHUB_REF_NAME"
Expand All @@ -334,8 +353,8 @@ jobs:
echo "published_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "source=https://github.com/$GITHUB_REPOSITORY/tree/$GITHUB_SHA"
echo "workflow=https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
} > "release-assets/CleanerX_${RELEASE_VERSION}_release-metadata.txt"
checksum_file="CleanerX_${RELEASE_VERSION}_SHA256SUMS.txt"
} > "release-assets/CleanerX-${RELEASE_VERSION}-release.txt"
checksum_file="CleanerX-${RELEASE_VERSION}-checksums.txt"
rm -f "release-assets/$checksum_file"
(cd release-assets && sha256sum * > "$checksum_file")
- name: Create draft release
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ The detailed routes, gates, limitations, and automated evidence live in the [mut
| Platform | Current boundary | Build output |
| --- | --- | --- |
| macOS 13+ | Apple Silicon and Intel | Unsigned `.app` and DMG |
| Linux x86_64 | WebKitGTK 4.1 desktop environment; CI uses Ubuntu 22.04 | Unsigned `.deb` and AppImage |
| Windows 10/11 x86_64 | WebView2 Runtime; MSVC C runtime is statically linked | Unsigned MSI and NSIS installers |
| Linux x64 / ARM64 | WebKitGTK 4.1 desktop environment; release CI uses native Ubuntu 22.04 runners | Unsigned `.deb` and AppImage |
| Windows 10/11 x64; Windows 11 ARM64 | WebView2 Runtime; MSVC C runtime is statically linked | Unsigned MSI and NSIS installers |

[CleanerX v0.1.0](https://github.com/BeaCox/CleanerX/releases/tag/v0.1.0) is the current stable release within the published compatibility matrix. Its macOS, Linux, and Windows artifacts are explicitly unsigned and not notarized; verify manually downloaded files against the release's SHA-256 checksums. See the [release policy](docs/open-source-release-plan.md) for the gates that separate source availability, mutation safety, and publisher identity.

Expand Down Expand Up @@ -135,11 +135,13 @@ make check
| --- | --- |
| `make app` | macOS: unsigned `.app` |
| `make bundles` | macOS: unsigned `.app` and DMG |
| `make linux` | Linux x86_64: unsigned `.deb` and AppImage |
| `make windows` | Windows x86_64 Developer PowerShell: unsigned MSI and NSIS installers |
| `make linux` | Native Linux architecture: unsigned `.deb` and AppImage |
| `make windows` | Native Windows Developer PowerShell: unsigned MSI and NSIS installers |

Use `TARGET=<rust-target-triple>` with bundle commands when selecting an explicit architecture. Native packages are written beneath `target/release/bundle/`.

Tagged release assets use the predictable form `CleanerX-{version}-{os}-{arch}.{ext}`, for example `CleanerX-0.2.0-linux-arm64.AppImage` and `CleanerX-0.2.0-windows-x64.exe`. The release warning, not a filename suffix, records that current builds are unsigned.

Unsigned builds may trigger Gatekeeper or SmartScreen. Verify that the binary came from the expected commit before approving it. Do not disable platform protections globally or trust a checksum as proof of publisher identity.

## Use CleanerX
Expand Down
2 changes: 1 addition & 1 deletion docs/open-source-release-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ An artifact is released from its exact tested tag. An earlier build is never pro
- The public key is pinned in `src-tauri/tauri.conf.json`. Release automation reads the private key only from the `TAURI_SIGNING_PRIVATE_KEY` GitHub Actions secret, while the maintainer keeps a recovery copy in the native credential store. It must never be committed, logged, or copied into a release artifact.
- Losing or rotating the private key without a signed transition strands installed builds on their pinned key. Key rotation therefore requires a release signed by the old key that embeds the new trust path before subsequent releases use the new key.
- The release job fails if any platform artifact or `.sig` file is absent. It creates `latest.json` only after all architecture-specific artifacts have been collected, and checksums include the manifest, signatures, and updater payloads.
- macOS arm64/x86_64, Windows x86_64 NSIS, and Linux x86_64 AppImage are the in-app update targets. MSI, `.deb`, DMG, and application ZIP artifacts remain manual distribution formats.
- macOS arm64/x86_64, Windows arm64/x86_64 NSIS, and Linux arm64/x86_64 AppImage are the in-app update targets. MSI, `.deb`, DMG, and application ZIP artifacts remain manual distribution formats.

## Pilot and defect policy

Expand Down
11 changes: 6 additions & 5 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ CleanerX currently has:
- encrypted `.cxb` backup/restore primitives, path guards, and an operation journal;
- optional, off-by-default cleanup backups with an explicit irreversible-deletion warning;
- macOS Apple Silicon and Intel `.app`/DMG builds;
- unsigned x86_64 Linux `.deb` and AppImage builds on Ubuntu 22.04, with a native Xvfb launch smoke test and an isolated Secret Service backup/restore round trip;
- unsigned x86_64 Windows MSI and NSIS builds, with a native launch smoke test and an isolated Credential Manager backup/restore round trip;
- release automation for unsigned x64 and ARM64 Linux `.deb` and AppImage builds on native Ubuntu 22.04 runners, with Xvfb launch smoke tests and an isolated x64 Secret Service backup/restore round trip; the published `v0.1.0` assets remain x64-only;
- release automation for unsigned x64 and ARM64 Windows MSI and NSIS builds on native runners, with launch smoke tests and an isolated x64 Credential Manager backup/restore round trip; the published `v0.1.0` assets remain x64-only;
- Windows application-data and package-manager launcher discovery, stdio-only Codex control transport, writer-process recognition, write-through atomic replacement, volume/file identity checks, owner validation, and junction/reparse-point rejection;
- reusable product CI with the complete Linux quality gate, cross-platform Rust tests, and native Linux/Windows launch smoke tests;
- reusable product CI with the complete Linux x64 quality gate, cross-platform Rust tests, and native x64/ARM64 Linux/Windows launch smoke tests;
- a published, explicitly unsigned and non-notarized [`v0.1.0`](https://github.com/BeaCox/CleanerX/releases/tag/v0.1.0) stable release with macOS, Linux, and Windows assets, updater signatures, build metadata, committed lockfiles, and SHA-256 checksums; and
- one SemVer tag workflow that reruns product CI, validates synchronized versions and `main` ancestry, builds every supported platform, and stages a GitHub Release for maintainer approval.
- one SemVer tag workflow that reruns product CI, validates synchronized versions and `main` ancestry, builds every supported platform/architecture, and stages consistently named `CleanerX-{version}-{os}-{arch}.{ext}` assets for maintainer approval.

This is a bounded stable release, not a promise that every Agent version, storage revision, native environment, or crash boundary has production-grade coverage.

Expand Down Expand Up @@ -107,9 +107,10 @@ Priority: maintain the published unsigned `v0.1.0` release and close the outstan

- Add Tauri smoke tests for launch, scan, read-only degradation, detail loading, review dialog, backup listing, and settings persistence on macOS 13+.
- Launch each architecture artifact on a clean supported environment and run an isolated mutation/backup/restore cycle with disposable Agent data.
- Record the first tagged native Linux ARM64 and Windows ARM64 package/install/update evidence; workflow support alone does not retroactively widen the published `v0.1.0` boundary.
- Confirm bundles contain no development URLs, private source-map paths, local preferences, test data, journals, or backup identities.
- Verify accessibility: keyboard-only navigation, focus order, contrast, system Chinese/English switching, dark mode, and reduced motion.
- Document reproducible local commands for both architectures and the supported Finder/System Settings opening path. Never instruct users to disable Gatekeeper globally or run broad quarantine-removal commands.
- Document reproducible local commands for each architecture and the supported Finder/System Settings opening path. Never instruct users to disable Gatekeeper globally or run broad quarantine-removal commands.
- Verify the manual signed updater on every supported updater package after draft artifacts exist: no startup/background request, invalid signatures fail closed, stable feeds exclude prereleases, and installation still requires two explicit user actions.

### Remaining pilot and compatibility evidence
Expand Down
Loading