diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index a09578e..114b89e 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,78 +1,126 @@ -# πŸ›οΈ MacOptimizer Pro Architecture +# MacOptimizer Pro Architecture -MacOptimizer Pro is designed with a **Clean, Layered, Unidirectional Data Flow (UDF)** architecture, ensuring high performance, memory safety, and defense-in-depth protection. +This document describes how the code is organised today. Paths are relative to +`Sources/MacOptimizer/`. ---- +## Package -## πŸ—οΈ System Overview +- One SwiftPM `executableTarget` (`MacOptimizer`) and one `testTarget` (`MacOptimizerTests`). +- swift-tools 6.0, Swift 6 language mode (strict concurrency), macOS 14 or later. +- No third-party dependencies. Localized resources live in `Resources/{en,tr}.lproj`. -```mermaid -graph TD - subgraph UI ["🎨 SwiftUI Presentation KatmanΔ±"] - Views["MainView / Dashboard / Memory / Cleaner / AppManager / Autonomous / Copilot"] - end - - subgraph State ["🧠 State Management"] - AppState["AppState (@MainActor ObservableObject)"] - end - - subgraph CoreSecurity ["πŸ›‘οΈ Security & Zero-Harm Engine"] - RiskClassifier["OperationRiskClassifier"] - SafetyEngine["SafetyPolicyEngine"] - Policies["PathProtection / ProcessProtection / AppProtection / LaunchProtection"] - SafeExec["SafeOperationExecutor (Atomic & Trash Fallback)"] - CmdSandbox["SandboxedCommandRunner (Whitelisted Executables)"] - end - - subgraph CoreTelemetry ["πŸ“Š Observability & Telemetry"] - SysMon["SystemMonitorService (Mach host_statistics64 & sysctl)"] - TelemetryStore["TelemetryStore (SQLite WAL Time-Series)"] - end - - subgraph AIPlatform ["πŸ€– AI & Diagnostics Platform"] - AIProvider["AIProvider Protocol"] - Heuristics["LocalHeuristicProvider (Offline)"] - Ollama["OllamaProvider (Local LLM)"] - NIM["NvidiaNIMProvider (Enterprise Cloud)"] - OpenAI["OpenAICompatibleProvider (Custom Endpoints)"] - end - - subgraph Operations ["βš™οΈ Domain Operations"] - CleaningPlan["CleaningPlan Engine (Dry-Run Lifecycle)"] - AppScanner["AppScannerService (Mach-O Binary Parser)"] - Uninstaller["AppUninstallerService (Orphan File Hunter)"] - Updates["AppUpdateCheckerService (Sparkle & Homebrew)"] - Watchdog["AutonomousGuardService (Background Healer)"] - end - - Views --> AppState - AppState --> CoreTelemetry - AppState --> AIPlatform - AppState --> Operations - Operations --> CoreSecurity - CoreSecurity --> Darwin["Darwin Mach Kernel & macOS FileSystem"] -``` - ---- +## Entry point -## 🧩 Architectural Layers +`App/MacOptimizerApp.swift` has a custom `@main`: -### 1. Presentation Layer (`Views/`) -* **SwiftUI + Liquid Glass Design System**: Dynamic blurred backgrounds, responsive grids (`LazyVGrid` with `GridItem(.adaptive(minimum: ...))`), and smart toolbar folding with `ViewThatFits`. -* **Zero UI Lag**: All telemetry computations, directory tree scanning, and network requests are executed on background actors. +- If `CLICommandRunner.shouldHandleCLI()` recognises a command (`status`, `clean`, `version`, + `help`), the CLI runs and the process exits. +- Otherwise the SwiftUI app starts with a main window (`MainView`) and a `MenuBarExtra`. -### 2. State Layer (`AppState.swift`) -* `@MainActor ObservableObject` that acts as the single source of truth for navigation, live gauges, AI recommendations, watchdog alarms, and background scan progress. +## Overview -### 3. Security Engine (`Core/Security/`) -* **`OperationRiskClassifier`**: Classifies operations into `.safe`, `.low`, `.medium`, `.destructive`, and `.forbidden`. -* **`PathProtectionPolicy`**: Canonicalizes paths with `URL.resolvingSymlinksInPath()` and protects system roots and user personal directories. -* **`ProcessProtectionPolicy`**: Shields PID 0/1 and 35+ critical macOS daemons from being killed. -* **`SafeOperationExecutor`**: Governs actual file removals and process termination. - -### 4. Telemetry & Storage (`Core/Telemetry/`) -* **`SystemMonitorService`**: Reads Mach VM statistics (`host_statistics64`) and kernel sysctl values in microseconds with near-zero CPU and battery footprint. -* **`TelemetryStore`**: Embedded SQLite database operating in WAL (Write-Ahead Logging) mode for thread-safe downsampled historical metrics. +```mermaid +graph TD + Views["SwiftUI views (Views/)"] --> AppState["AppState (@MainActor, user-driven state)"] + Views --> Metrics["LiveMetricsStore (live metrics only)"] + AppState --> Coordinator["MonitoringCoordinator (one owned sampling loop)"] + Coordinator --> Monitor["SystemMonitorService (Mach, sysctl, IOKit, getifaddrs, ps)"] + Coordinator --> Metrics + Coordinator --> Telemetry["TelemetryStore (SQLite, 1 row per minute, 48 h)"] + Coordinator --> Watchdog["AutonomousGuardService (alert rules)"] + AppState --> Services["Feature services (junk, apps, duplicates, startup, updates, maintenance, audit, AI)"] + Services --> Plan["CleaningPlan (preview)"] + Plan --> Executor["SafeOperationExecutor (confirmation, re-validation, Trash)"] + Executor --> Policy["SafetyPolicyEngine + protection policies"] + Services --> Runners["SandboxedCommandRunner / SystemCommandRunner"] + Runners --> ProcExec["ProcessExecutor (no shell, timeouts, bounded output)"] +``` -### 5. Multi-Provider AI Platform (`Infrastructure/AI/`) -* Completely decoupled from raw system commands. AI generates structured `AIInsight` and `AIAction` recommendations which must pass through the `SafetyPolicyEngine` and require user confirmation before execution. +## Layers + +| Folder | Contents | +| --- | --- | +| `App/` | `AppState`: a `@MainActor ObservableObject` singleton holding navigation, scan results, alerts, chat and history. `MacOptimizerApp` and the menu bar view. | +| `Core/Monitoring/` | `MonitoringCoordinator` (one owned async loop), `MetricsSchedulePolicy` (which metric tiers are due, depending on visibility and the watchdog), `LiveMetricsStore` (publishes only changed metric values). | +| `Core/Concurrency/` | `ProcessExecutor` (child processes with concurrent pipe draining, output cap, SIGTERM then SIGKILL on timeout, cancellation), `runBlocking`, `CancellationFlag`, `ProgressThrottle`, `RingBuffer`. | +| `Core/Security/` | `PathProtectionPolicy`, `ProcessProtectionPolicy`, `ApplicationProtectionPolicy`, `LaunchItemProtectionPolicy`, `SafetyPolicyEngine`, `OperationRiskClassifier`, `SafeOperationExecutor`. | +| `Core/Operations/` | `CleaningPlan`, `CLICommandRunner`, `SandboxedCommandRunner` (allow-list of absolute executable paths). | +| `Core/Telemetry/` | `TelemetryStore`: SQLite in WAL mode at `~/Library/Application Support/com.osmancagrigenc.MacOptimizer/telemetry.sqlite`, downsampled in SQL when read. | +| `Services/` | `SystemMonitorService`, `JunkCleanerService`, `AppScannerService`, `AppUninstallerService`, `AppUpdateCheckerService`, `DuplicateFileFinderService`, `StartupManagerService`, `MaintenanceService`, `PrivacyAuditService`, `MemoryOptimizerService` (process termination only), `AutonomousGuardService`, `AIAssistantService`, `NvidiaNIMService`. Most are actors; the scanners are stateless `Sendable` classes that do blocking I/O off the cooperative thread pool. Each has a `.shared` instance. | +| `Infrastructure/AI/` | The `AIProvider` protocol with two implementations: `LocalHeuristicProvider` (offline, default) and `NvidiaNIMProvider` (cloud, opt-in). | +| `Infrastructure/Persistence/` | `KeychainManager` (`kSecAttrAccessibleWhenUnlockedThisDeviceOnly`), used for the NVIDIA NIM API key. | +| `Helpers/` | `SafetyGuard` (older checks still used for processes, apps and launch items), `SystemCommandRunner` (runs a given executable with arguments, no shell), `XMLParserHelper` (Sparkle appcasts), `FileSizeCalculator`, `MachOArchitectureDetector`, `VersionComparator`, `ByteFormatter`. | +| `Models/` | Value types for metrics, junk items, apps, alerts, AI and watchdog configuration. | +| `Views/` | Feature screens: Dashboard, Memory, Junk Cleaner, Duplicate Finder, App Manager, Updates, Startup, Maintenance, Security, History, Watchdog, AI, Settings, plus shared components. | +| `L10n.swift` | Localization helper over the per-area string tables (see [docs/LOCALIZATION.md](docs/LOCALIZATION.md)). | + +## Monitoring + +`MonitoringCoordinator` runs a single loop. Each metric tier (core, disk, battery, telemetry, +hardware, processes) has its own interval, and the loop slows down when the window is hidden: +2.5 s for core metrics while visible, 10 s while hidden with the watchdog on, 60 s while hidden +and idle. `/bin/ps` runs only when a process list or the watchdog needs it. Details and the +measurements behind them are in [docs/PERFORMANCE_REPORT.md](docs/PERFORMANCE_REPORT.md). + +The watchdog is `AutonomousGuardService`, evaluated by this loop. It therefore runs only while +the app process is running; there is no LaunchAgent or background helper. + +## Destructive operations + +1. A scan builds a `CleaningPlan`. Paths are canonicalised and classified; forbidden paths and + Trash items are left out of the plan. +2. The UI shows the plan. The CLI prints it and needs `--execute --yes`. +3. `SafeOperationExecutor.removeFile` evaluates the path with `SafetyPolicyEngine`, throws when a + `requiresConfirmation` decision has no confirmation, re-resolves the path before acting, and + moves the item to the Trash. Permanent removal is allowed only for paths accepted by + `PathProtectionPolicy.isCleanableCachePath`. +4. `SafeOperationExecutor.emptyTrash` permanently removes entries that are directly inside + `~/.Trash`, after a separate confirmation. + +The junk cleaner, uninstaller, duplicate finder and startup manager all call the executor with +`moveToTrash: true`. + +## Commands + +- `SandboxedCommandRunner` runs only executables from the `ApprovedExecutable` allow-list + (`dscacheutil`, `killall`, `mdutil`, `qlmanage`, `lsregister`, `atsutil`, `launchctl`, + `csrutil`, `spctl`, `defaults`, `socketfilterfw`), drops arguments containing shell + metacharacters, and has a 15 s default timeout. +- `SystemCommandRunner` runs a fixed executable with an argument array (used for `/bin/ps`, + `/bin/kill` and `brew`). There is no shell execution anywhere in the app. + +## Data and persistence + +| Data | Where | +| --- | --- | +| Settings, AI and watchdog configuration, operation history (last 500) | UserDefaults (`MacOptimizer_NIMConfig`, `MacOptimizer_AutonomousConfig`, `MacOptimizer_History`, …) | +| NVIDIA NIM API key | Keychain | +| Telemetry time series (1 row per minute, pruned after 48 h) | SQLite file above, not encrypted | + +There is no audit log of file operations. + +## Networking + +- NVIDIA NIM (`https://integrate.api.nvidia.com/v1`), only when the user enabled it. Plain HTTP is + refused except for localhost. +- Sparkle appcasts of installed apps (plain HTTP feeds are allowed). +- The VS Code update API. +- `brew`, which may contact its own servers. + +## Build and release + +- `Scripts/build_app.sh` builds a release binary and assembles `MacOptimizer.app` with a generated + Info.plist. It does not sign the app. +- GitHub Actions: `ci.yml` (build, full test suite, host-state canary, app bundle), `release.yml` + (DMG and build-provenance attestation on tags, no signing yet), `security.yml` (Gitleaks and a + dependency inventory). +- Developer ID signing, notarization and a single version source are being added for v3.1.0. + +## Known limitations + +- `AppState` is large and several views call services directly. +- Two safety layers overlap: `Helpers/SafetyGuard` and `Core/Security`. +- Services are singletons without dependency injection (tests inject runners and directories + where needed). +- Homebrew update detection parses `brew outdated --json=v2` and has not been verified against + every Homebrew version. diff --git a/BENCHMARKS.md b/BENCHMARKS.md index 9817128..1c09777 100644 --- a/BENCHMARKS.md +++ b/BENCHMARKS.md @@ -1,43 +1,38 @@ -# 🏎️ MacOptimizer Pro Benchmarks & Performance Metrics +# Benchmarks -This document outlines the performance benchmarks, measurement methodologies, and hardware test environments for MacOptimizer Pro. +There are currently **no verified benchmark figures** for MacOptimizer Pro. ---- +Earlier versions of this page and of the README listed speed-ups (for example Mach-O detection +"~120x faster" than `lipo`, telemetry reads "< 0.02 ms", a "0.42 s" scan of 50,000 files, +"1.2 GB/s" hashing and "~0.01 %" watchdog CPU). None of them had a reproducible measurement in +this repository, and some described code that did not exist at the time (the junk scan was not +parallel). They have been removed. -## πŸ–₯️ Test Environment +## What is measured -* **Hardware**: Apple MacBook Pro 14" (Apple M3 Pro, 18 GB Unified Memory) -* **OS**: macOS 15.0 (Sequoia) / macOS 14.5 (Sonoma) -* **Storage**: 512 GB Apple NVMe SSD (APFS) -* **Compiler**: Swift 5.10 / Xcode 15.4 (`-O -whole-module-optimization`) +[docs/PERFORMANCE_BASELINE.md](docs/PERFORMANCE_BASELINE.md) and +[docs/PERFORMANCE_REPORT.md](docs/PERFORMANCE_REPORT.md) contain figures from the monitoring and +concurrency hardening work. Each figure is labelled as measured (run against the source), simulated +(the scheduler driven by a fake clock), static (counted from the code) or +`REQUIRES_INSTRUMENTS_VALIDATION` (not measured yet). ---- +## How to measure -## πŸ“Š Benchmark Results +- **Resource use of the app**: build a release app with `./Scripts/build_app.sh` and follow the + Instruments runs listed at the end of [docs/PERFORMANCE_REPORT.md](docs/PERFORMANCE_REPORT.md) + (Allocations, Leaks, Time Profiler, System Trace, Energy Log). +- **A single operation**: time it on your own machine and state the hardware, macOS version, + build configuration and data set (for example the number and size of files) with the result. -> **Note (hardening pass):** the figures below predate the performance/concurrency hardening pass and -> were not reproducible from the code at that time (e.g. the junk walk was serialised on an actor, -> not parallel). See [`docs/PERFORMANCE_BASELINE.md`](docs/PERFORMANCE_BASELINE.md) and -> [`docs/PERFORMANCE_REPORT.md`](docs/PERFORMANCE_REPORT.md) for measured/derived numbers and the -> Instruments runs that validate them. +Please include that context with any number you contribute to this page. -| Benchmark Metric | Traditional Shell/Script Method | MacOptimizer Pro Native Architecture | Improvement Factor | -| :--- | :--- | :--- | :--- | -| **Mach-O Architecture Detection** | `lipo -archs /Path/to/binary` (~ 4.8 ms per app) | `MachOArchitectureDetector` (Direct Header Bytes) (~ 0.04 ms per app) | **~ 120x Faster** | -| **System Telemetry Retrieval** | Parsing `/bin/ps` and `top -l 1` (~ 45 ms) | Darwin Mach `host_statistics64` & `sysctl` (< 0.02 ms) | **~ 2200x Faster** | -| **Multi-Category Junk Scanning** | Sequential single-thread directory walk (~ 4.2 s for 50k files) | Parallel `TaskGroup` multi-core directory walk (~ 0.72 s for 50k files) | **~ 5.8x Faster** | -| **App Leftovers Discovery** | Full root disk `find` recursive traversal (~ 12.5 s) | Targeted `~/Library/Application Support` orphan match (~ 0.35 s) | **~ 35x Faster** | -| **Watchdog Idle CPU Usage** | Periodic bash cron / poller (~ 1.5% - 3.0% CPU) | Async Swift background actor with timer (~ 0.01% CPU) | **Negligible CPU Footprint** | +## Design notes ---- +These describe how the code works, not how fast it is: -## πŸ”¬ Reproducing the Benchmarks - -You can run the built-in test suite to verify binary parsing and telemetry throughput: -```bash -# Run all unit tests with execution timings -swift test --enable-code-coverage -``` - -### Mach-O Architecture Detector Benchmark -Direct header parsing loads the first 4096 bytes of the binary using `FileHandle` and reads the 32-bit magic number (`0xFEEDFACF` for 64-bit Mach-O, `0xCAFEBABE` for Universal Fat binaries). This completely bypasses the macOS process creation overhead of spawning `/usr/bin/lipo`. +- `MachOArchitectureDetector` reads the first 4096 bytes of a binary with `FileHandle` and checks + the magic number (`0xFEEDFACF` for 64-bit Mach-O, `0xCAFEBABE` for universal binaries) instead + of spawning `lipo`. +- Live metrics come from `host_statistics64`, `sysctl`, IOKit and `getifaddrs`. Only the process + list uses `/bin/ps`, and only while a screen or the watchdog needs it. +- The duplicate finder compares a 64 KB prefix before hashing whole files with SHA-256. diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fc790d..4562513 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,32 +1,97 @@ -# πŸ“ Changelog +# Changelog -All notable changes to **MacOptimizer Pro** are documented in this file following the [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) standard. +All notable changes to MacOptimizer Pro are documented in this file. The format follows +[Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ---- +## [3.1.0] - Unreleased -## [2.1.0] - 2026-08-28 +The safety release. v2.1.0–v3.0.0 contain known safety defects; use v3.1.0 or later. -### Added -* **Zero-Harm Security Policy Engine**: Refactored monolithic safety validation into modular policy evaluators (`PathProtectionPolicy`, `ProcessProtectionPolicy`, `ApplicationProtectionPolicy`, `LaunchItemProtectionPolicy`, `SafetyPolicyEngine`). -* **Symlink Resolution & Traversal Guard**: Integrated `URL.resolvingSymlinksInPath()` into path evaluation to neutralize symlink-based data loss attacks. -* **Operation Risk Classifier**: Introduced `OperationRisk` enum (`.safe`, `.low`, `.medium`, `.destructive`, `.forbidden`) to classify every user or automated action before execution. -* **Dry-Run Cleaning Engine**: Added `CleaningPlan` supporting two-phase preview, byte estimation, and user confirmation. -* **macOS Keychain Integration**: Created `KeychainManager` utilizing `Security.framework` for encrypted credential storage and automatic migration from `UserDefaults`. -* **Multi-Provider AI Architecture**: Added `AIProvider` protocol supporting `LocalHeuristicProvider` (100% offline), `OllamaProvider` (local LLMs), `NvidiaNIMProvider` (cloud), and `OpenAICompatibleProvider`. -* **Sandboxed Command Runner**: Whitelist-only execution mechanism with argument sanitization and 15s watchdog protection. -* **SQLite Telemetry Store**: High-concurrency WAL-mode SQLite time-series storage for system performance metrics. -* **Expanded Test Suite**: 23 test suites containing 120+ property-based assertions covering path protection, symlink attacks, daemon protection, dry-run plans, and AI providers. -* **Open Source Governance**: Added Apache-2.0 License, `SECURITY.md` (STRIDE threat model), `CONTRIBUTING.md`, `ARCHITECTURE.md`, `PRIVACY.md`, `ROADMAP.md`, and `BENCHMARKS.md`. +### Security + +- Removed a command injection in the update screen: a remote Sparkle appcast could make the app + run shell code. The shell runner is gone; Homebrew upgrades run `brew` directly with a + validated cask token, and appcast links open only for `http`/`https` URLs. (#1) +- One deletion pipeline for the app and the CLI: plan preview, enforced confirmation in + `SafeOperationExecutor`, re-validation of the path right before acting, Trash by default, and + permanent removal only inside approved cache folders. "Smart optimize", "Empty Trash", the AI + clean action and the CLI no longer delete without a preview and confirmation. (#3) +- Emptying the Trash is a separate, confirmed action that removes Trash entries only, never the + targets of symlinks. Trash items are no longer pre-selected. (#3) +- Uninstaller leftovers are opt-in and matched by a validated bundle identifier. (#3) + +### Changed + +- The CLI needs `--execute --yes` to clean and `--include-trash` to touch the Trash. It no longer + treats Cocoa launch arguments (such as `-AppleLanguages`) as commands. (#3, #7) +- AI assistant: local heuristics are the default; NVIDIA NIM runs only after an in-app disclosure + is accepted; running app names and PIDs are sent only with a separate opt-in. (#4) +- Monitoring runs in one owned loop with tiered, visibility-aware sampling; process execution + drains pipes concurrently with bounded output and SIGTERM/SIGKILL timeouts; scans run in + parallel and can be cancelled; in-memory collections are bounded. (#1) +- Telemetry history is now actually recorded (one row per minute, kept for 48 hours). (#1) +- English and Turkish localization. The app follows the macOS system language; the CLI and the + prompts sent to NVIDIA NIM are English. (#7–#19) + +### Fixed + +- Maintenance commands report their real exit codes instead of always reporting success. (#5) +- The security score no longer adds points for a disabled firewall or unconditionally; states + that cannot be read are shown as unknown. (#5) +- The CLI `status` command measures CPU from two real samples instead of printing a fixed + value. (#5) +- Battery health is calculated correctly on Apple Silicon. (#5) +- Charts no longer show made-up seed data. (#5) + +### Removed + +- RAM purge (the app, the menu bar, the CLI `purge-ram` command, the AI action and the watchdog + auto-heal option). It could not free memory without administrator rights but reported + success. (#5) +- The unused Ollama and OpenAI-compatible AI providers. (#4) ---- +### Tests and CI -## [2.0.0] - 2026-08-28 +- The test suite is hermetic: injected command runners, temporary SQLite files, a fake home + folder and a throwaway Keychain item. CI runs all tests on macOS with Xcode 16.4 (Swift 6) and + checks that the clipboard and Keychain are unchanged. The suite now has 87 test methods. + (#2, #6, #7) +- Gitleaks runs as a CLI in CI. (#2) + +### Release (in progress) + +- Developer ID signing, notarization and one version source for the app, the CLI and the tag are + being prepared. They are not merged yet. + +## [2.2.0] – [3.0.0] - 2026-08-28 + +Released the same day as 2.1.0 without changelog entries; see the +[GitHub releases](https://github.com/Codifya/MacOptimizer/releases). They added the cleaning plan +preview, Swift Charts, thermal and swap metrics, the SQLite telemetry store, the watchdog rules, +the menu bar extra, the CLI, developer cache cleaning, the uninstaller, the security overview, the +duplicate finder, battery and network telemetry. **These releases are unsafe**: see 3.1.0. + +## [2.1.0] - 2026-08-28 + +First public release. **Unsafe**: see 3.1.0. ### Added -* **Native Liquid Glass UI**: Modern macOS Sonoma/Sequoia aesthetic with responsive grid layouts. -* **Microsecond Mach-O Header Parser**: Direct binary header inspection without spawning `lipo` subprocesses. -* **Parallel Junk Scanner**: Concurrent file system analysis using Swift `TaskGroup`. -* **Deep App Uninstaller**: Discovery of orphaned caches and preferences across `~/Library`. -* **Autonomous Guard**: 7/24 background watchdog detecting runaway processes and memory pressure. -* **Sparkle & Homebrew Updater**: Real-time update checks for installed applications. -* **macOS Maintenance Scripts**: QuickLook cache reset, DNS flush, Spotlight reindexing, and safe RAM release. + +- Modular safety policies (`PathProtectionPolicy`, `ProcessProtectionPolicy`, + `ApplicationProtectionPolicy`, `LaunchItemProtectionPolicy`, `SafetyPolicyEngine`) with + symlink resolution, and the `OperationRisk` levels. +- `CleaningPlan` for a preview before cleaning. (In this release some delete actions bypassed it.) +- `KeychainManager` for the API key, with migration from UserDefaults. +- An `AIProvider` protocol. Only the local heuristics and NVIDIA NIM were ever used; the Ollama + and OpenAI-compatible providers were never wired into the app and were removed in 3.1.0. +- `SandboxedCommandRunner` with an executable allow-list and a 15 s timeout. (A separate shell + runner still existed and was removed in 3.1.0.) +- An SQLite telemetry store. (Nothing was written to it until 3.1.0.) +- A test suite of 23 test methods in one file (earlier notes called them "23 suites with 120+ + assertions"). There were 36 by v3.0.0. +- Apache-2.0 license and the project documents. +- Also included (earlier notes listed them as a separate 2.0.0, which was never tagged): the + SwiftUI interface, the Mach-O architecture detector, the junk scanner, the app uninstaller, + Sparkle and Homebrew update checks, maintenance commands and an in-app watchdog. The watchdog + ran only while the app was open (it was described as "7/24"), and the "safe RAM release" did + not reliably free memory. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index facc7c8..5d04e19 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,68 +1,67 @@ -# 🀝 Contributing to MacOptimizer Pro +# Contributing to MacOptimizer Pro -Thank you for your interest in contributing to **MacOptimizer Pro**! We welcome bug reports, feature suggestions, architecture improvements, and code contributions from the macOS open-source community. +Thank you for your interest in contributing. Bug reports, suggestions and pull requests are +welcome. ---- +## Code of conduct -## 🧭 Code of Conduct +Be respectful, inclusive and constructive. -All contributors and maintainers are expected to adhere to standard respectful, inclusive, and professional communication standards. - ---- - -## πŸ› οΈ Development Setup +## Development setup ### Prerequisites -* macOS 14.0 (Sonoma) or macOS 15.0+ (Sequoia) -* Xcode 15.0+ / Xcode 16.0+ (with Command Line Tools installed: `xcode-select --install`) -* Swift 5.9+ -* Git -### Building from Source -```bash -# Clone the repository -git clone https://github.com/osmancagrigenc/MacOsOptimizer.git -cd MacOsOptimizer +- macOS 14 or later +- Xcode 16 or later (Swift 6 toolchain); CI uses Xcode 16.4 +- Git -# Run unit tests -swift test +### Building from source -# Build debug binary -swift build +```bash +git clone https://github.com/Codifya/MacOptimizer.git +cd MacOptimizer -# Build standalone .app bundle -./Scripts/build_app.sh +swift build # debug build +swift test # run the test suite +./Scripts/build_app.sh # build MacOptimizer.app (unsigned) ``` ---- - -## πŸ“ Architecture & Coding Guidelines - -1. **Zero-Harm First**: Every filesystem or process operation MUST be validated through `SafetyPolicyEngine`. Never write direct file removal code without policy checks. -2. **Swift Concurrency**: Use native Swift `async`/`await`, `TaskGroup`, and actors. Avoid legacy dispatch queues or callback pyramids. -3. **Darwin & Native APIs Over Shell Commands**: Prefer Darwin Mach Kernel C APIs (`host_statistics64`, `sysctlbyname`), `FileManager`, and `ProcessInfo` over executing `/bin/sh` or `/bin/ps`. -4. **Clean UI & Liquid Glass**: Adhere to SwiftUI best practices with fluid responsive sizing (`ViewThatFits`, `LazyVGrid` adaptive columns, `maxWidth: .infinity`). -5. **No Secrets in Code**: Never commit API keys, personal paths, or tokens. API keys must use `KeychainManager`. - ---- - -## πŸ§ͺ Testing Requirements +## Guidelines + +1. **Safety first.** Every file removal must go through `SafeOperationExecutor` with a + `CleaningPlan` the user has reviewed and confirmed. Never call `FileManager.removeItem` or + `trashItem` directly from a feature. +2. **No shell.** Run external tools through `SandboxedCommandRunner` (add the absolute path to + `ApprovedExecutable`) or `SystemCommandRunner` with an argument array. Never build a shell + command string, and never pass remote data as a command. +3. **Swift concurrency.** Use `async`/`await` and actors. Keep blocking file I/O off the + cooperative thread pool (see `runBlocking`), and make long scans cancellable. +4. **Native APIs first.** Prefer Darwin, IOKit, `FileManager` and `ProcessInfo` over spawning + processes. +5. **Localization.** User-facing strings go through `L10n` with English and Turkish entries. See + [docs/LOCALIZATION.md](docs/LOCALIZATION.md). CLI output stays English. +6. **No secrets in code.** API keys go through `KeychainManager`. +7. **Honest results.** Report the real outcome of an operation (exit codes, bytes actually + freed). Do not show success for work that did not happen. + +## Tests + +- New features and policy changes need tests in `Tests/MacOptimizerTests/`. +- Tests must be hermetic: they must not change the machine they run on. Use temporary + directories, a fake home folder, injected command runners and throwaway Keychain items. CI + checks that the clipboard and Keychain are unchanged after the run. +- Run the suite before opening a pull request: -* All new features and policy changes **must include unit tests** in `Tests/MacOptimizerTests/`. -* Verify tests before opening a pull request: ```bash - swift test --enable-code-coverage + swift test ``` -* All property-based safety tests must pass with 0 failures. ---- +## Pull requests -## πŸš€ Pull Request Workflow +1. Fork the repository and create a descriptive branch. +2. Use Conventional Commits (`feat:`, `fix:`, `refactor:`, `docs:`, `test:`). +3. Make sure `swift build` and `swift test` pass. +4. Open a pull request against `main` with a summary of the change, the motivation and how you + tested it. Keep the documentation in line with what the code does. -1. Fork the repository and create a descriptive branch: - ```bash - git checkout -b feature/awesome-telemetry-chart - ``` -2. Commit your changes following standard Conventional Commits (`feat:`, `fix:`, `refactor:`, `docs:`, `test:`). -3. Ensure `swift test` passes cleanly. -4. Open a Pull Request against the `main` branch with a clear summary of changes, motivation, and test coverage evidence. +Security problems: please follow [SECURITY.md](SECURITY.md) instead of opening a public issue. diff --git a/MASTER_IMPLEMENTATION_PROMPT.md b/MASTER_IMPLEMENTATION_PROMPT.md index e063ce2..7877df0 100644 --- a/MASTER_IMPLEMENTATION_PROMPT.md +++ b/MASTER_IMPLEMENTATION_PROMPT.md @@ -1,3 +1,5 @@ +> **Historical document:** this is the original AI generation prompt for v3.0, kept for reference. It describes intended goals, not current behavior; see [README.md](README.md) and [ARCHITECTURE.md](ARCHITECTURE.md) for what the code actually does. + # πŸš€ MASTER_IMPLEMENTATION_PROMPT: MacOptimizer Pro v3.0 Transformation > **Mission**: Transform MacOptimizer into an enterprise-grade, security-first, open-source **Native macOS System Health & Optimization Toolkit** governed by a **Zero-Harm Architecture (Defense-in-Depth)**. diff --git a/PRIVACY.md b/PRIVACY.md index 2b1d2e0..656885f 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -1,28 +1,45 @@ -# πŸ›‘οΈ Privacy Policy & Commitments +# Privacy -**MacOptimizer Pro** is committed to maximum transparency, data security, and user privacy. +This page describes what MacOptimizer Pro stores on your Mac and what it sends over the network. ---- +## What stays on your Mac -## πŸ”’ Core Privacy Principles +- System monitoring, cleaning, duplicate finding and the watchdog run locally. +- Telemetry history (CPU, memory, memory pressure and disk use, one sample per minute) is stored + in `~/Library/Application Support/com.osmancagrigenc.MacOptimizer/telemetry.sqlite` and pruned + after 48 hours. The file is not encrypted. +- Settings and the list of completed operations (the last 500) are stored in the app's + preferences (UserDefaults). +- None of this is uploaded anywhere. -1. **Offline-First by Default**: - * All system monitoring, memory analysis, disk cleaning, and watchdog features execute 100% locally on your Mac. - * Telemetry metrics and optimization logs never leave your device. +## No tracking -2. **Zero Third-Party Telemetry & Tracking**: - * MacOptimizer contains **NO tracking SDKs, NO analytics beacons, NO advertising frameworks, and NO fingerprinting**. +MacOptimizer Pro contains no analytics, tracking, advertising or crash-reporting SDKs. -3. **Secure Credential Storage**: - * Any API keys you choose to configure (e.g. NVIDIA NIM API Key or custom OpenAI endpoint tokens) are stored exclusively in the encrypted **macOS Keychain** (`Security.framework`). - * They are never saved in plain text or synced to external servers. +## API keys -4. **Transparent AI Diagnostics**: - * Built-in local heuristics are the default and work offline. NVIDIA NIM is disabled by default and requires accepting an in-app disclosure before its first request. - * NVIDIA NIM receives the Mac hardware model, chip, macOS version, RAM/CPU/disk percentages, detected junk size, and the chat messages sent to the assistant. The API key is sent only as the HTTPS authorization credential and is not part of the request body. - * Running app names and process IDs are excluded by default. The separate β€œΓ‡alışan uygulama adlarΔ±nΔ± dahil et” setting opts them into NVIDIA NIM requests. File paths and file contents are not included in AI requests. +An NVIDIA NIM API key you configure is stored in the macOS Keychain. It is not written to +UserDefaults and is sent only to the NVIDIA NIM endpoint as the HTTPS authorization credential. -5. **Other Network Requests**: - * App update checks read the configured Sparkle appcasts of installed apps; a feed configured with plain HTTP is contacted over HTTP. - * The VS Code update checker contacts the VS Code update API. - * Homebrew update and package operations invoke `brew`, which may contact its configured repositories and services. +## AI assistant + +- Built-in local heuristics are the default and work offline. +- NVIDIA NIM is disabled by default and requires accepting an in-app disclosure before its first + request. +- NVIDIA NIM receives the Mac hardware model, chip, macOS version, RAM/CPU/disk percentages, + detected junk size, the number of apps with pending updates, and the recent chat messages sent + to the assistant. The API key is sent only as the HTTPS authorization credential and is not + part of the request body. +- Running app names and process IDs are excluded by default. The separate "Include running app + names" setting opts them into NVIDIA NIM requests. File paths and file contents are not + included in AI requests. +- Testing the connection or refreshing the model list contacts the configured NVIDIA NIM + endpoint with your key. + +## Other network requests + +- App update checks read the configured Sparkle appcasts of installed apps; a feed configured + with plain HTTP is contacted over HTTP. +- The VS Code update checker contacts the VS Code update API. +- Homebrew update and package operations invoke `brew`, which may contact its configured + repositories and services. diff --git a/README.md b/README.md index d1a98bb..c642094 100644 --- a/README.md +++ b/README.md @@ -1,138 +1,161 @@ -# ⚑ MacOptimizer Pro +# MacOptimizer Pro -> **Safety notice:** Releases [v2.1.0–v3.0.0](https://github.com/Codifya/MacOptimizer/releases) contain known safety defects. Do not use these releases. A fixed, signed release is in progress. +> **Safety notice:** Releases [v2.1.0–v3.0.0](https://github.com/Codifya/MacOptimizer/releases) contain known safety defects. Do not use them; use v3.1.0 or later. v3.1.0 is being prepared now and will be the first Developer ID-signed and notarized release.
-![macOS 14+](https://img.shields.io/badge/macOS-14.0%2B%20%28Sonoma%2FSequoia%29-blue?logo=apple&style=flat-square) -![Swift 6.0](https://img.shields.io/badge/Swift-6.0-orange?logo=swift&style=flat-square) -![Architecture](https://img.shields.io/badge/Architecture-Apple%20Silicon%20%7C%20Intel-purple?style=flat-square) +![macOS 14+](https://img.shields.io/badge/macOS-14.0%2B-blue?logo=apple&style=flat-square) +![Swift 6](https://img.shields.io/badge/Swift-6-orange?logo=swift&style=flat-square) ![License](https://img.shields.io/badge/License-Apache%202.0-green?style=flat-square) -![Security](https://img.shields.io/badge/Security-Zero--Harm%20Engine-red?logo=apple&style=flat-square) -![Tests](https://img.shields.io/badge/Tests-36%20Suites%20%7C%20200%2B%20Passed-success?style=flat-square) -**Security-First, Open-Source, Native macOS System Health & Optimization Toolkit** +**An open-source, native macOS system health and cleanup utility written in Swift and SwiftUI.** -[Features](#-key-features) β€’ [Zero-Harm Architecture](#-zero-harm-architecture) β€’ [AI Platform](#-multi-provider-ai-platform) β€’ [CLI Companion](#-headless-cli-companion) β€’ [Benchmarks](#-performance-benchmarks) β€’ [Installation](#-installation) β€’ [Contributing](#-contributing) +[Features](#features) β€’ [How deletion works](#how-deletion-works) β€’ [AI assistant](#ai-assistant) β€’ [Command line](#command-line) β€’ [Installation](#installation) β€’ [Contributing](#contributing)
--- -## πŸ“– Overview - -**MacOptimizer Pro** is an open-source, enterprise-grade system health, telemetry, and optimization toolkit crafted exclusively for macOS. Built purely in **Swift 6** with **SwiftUI**, native **Darwin Mach Kernel APIs**, and **IOKit**, it delivers microsecond-level hardware telemetry, autonomous watchdog protection, and memory optimization without the bloat, battery drain, or questionable security practices of traditional cleaners. - ---- - -## ✨ Key Features - -* πŸ“Š **Low-Overhead Telemetry**: Direct Darwin Mach kernel inspection (`host_statistics64`, `sysctlbyname`) for memory pressure, swap usage, CPU load, thermal throttling, and battery health with near-zero CPU footprint. -* πŸ›‘οΈ **Zero-Harm Defense-in-Depth**: Modular safety policy engine preventing accidental file deletion, symlink traversal attacks, and macOS system daemon termination. -* πŸ” **Two-Phase Dry-Run Cleaning**: Scans caches, developer build leftovers (Xcode `DerivedData`, CocoaPods, NPM, Yarn, Cargo, UV, Poetry, Homebrew), browser caches, and orphan app directories with complete preview and byte estimation before execution. -* πŸ“‘ **High-Speed SHA-256 Duplicate Finder**: Cryptographic hash clustering to detect identical duplicate files across Downloads, Documents, and Pictures with original file preservation. -* πŸ”’ **Security & Privacy Posture Audit**: Live auditing of System Integrity Protection (SIP), Gatekeeper code-signing, Application Firewall state, and TCC permissions with 0–100 hardening score. -* 🌐 **Real-time Network Throughput**: Microsecond `getifaddrs` bandwidth monitoring displaying live download/upload speeds and local IP configuration. -* πŸ”‹ **Deep Battery Health & Thermals**: IOKit AppleSmartBattery inspection measuring cycle count, true health percentage, battery temperature (Β°C), and overheating alerts (>38Β°C). -* πŸ’» **Headless Terminal CLI Companion**: First-class command-line runner (`MacOptimizer status`, `clean --dry-run`, `purge-ram`). -* πŸš€ **Microsecond Binary Architecture Parser**: Direct Mach-O binary header inspection to distinguish Apple Silicon (ARM64), Universal, and Intel (x86_64) binaries without slow subprocess calls. -* πŸ€– **Multi-Provider AI Copilot**: Decoupled AI diagnostic engine supporting **100% Offline Heuristics**, **Local Ollama LLMs**, and **Enterprise Cloud NIM** (Llama 3.3, DeepSeek R1). -* πŸ• **7/24 Autonomous Watchdog**: Background watchdog that detects memory spikes, swap exhaustion, thermal throttling, and runaway processes with auto-healing. -* πŸ” **Keychain Secret Storage**: Encrypted credential storage via native macOS `Security.framework`. -* πŸ“± **Liquid Glass Responsive UI**: Adaptive layouts scaling smoothly from 13" MacBook Airs up to 5K Studio Displays, MenuBar Extra popover, and Split View. - ---- - -## πŸ›‘οΈ Zero-Harm Architecture - -MacOptimizer adheres to strict defense-in-depth principles: - -```mermaid -graph TD - UserAction["User / CLI / AI Trigger"] --> Risk["OperationRiskClassifier (.safe / .low / .medium / .destructive / .forbidden)"] - Risk --> Policy["SafetyPolicyEngine (Modular Security Rules)"] - Policy --> Symlink["Symlink & Path Canonicalization (resolvingSymlinksInPath)"] - Symlink --> DryRun["Dry-Run Preview (CleaningPlan)"] - DryRun --> Confirmation["User Explicit Confirmation / --execute"] - Confirmation --> Executor["SafeOperationExecutor (Atomic & Trash Fallback)"] - Executor --> Audit["Encrypted SQLite WAL Audit Trail"] -``` - -1. **System & User Path Protection**: Hard boundaries protecting system root directories (`/System`, `/Library`, `/usr`, `/private`) and essential user directories (`~`, `~/Desktop`, `~/Documents`, `~/Downloads`, `~/.ssh`, `~/.gnupg`, `~/Library/Keychains`). -2. **Symlink Attack Resistance**: Canonicalizes all filesystem paths with `URL.resolvingSymlinksInPath()` before evaluating deletion permissions. -3. **Anti-Kernel Panic Protection**: Blocks termination of PID 0 (`kernel_task`), PID 1 (`launchd`), and 35+ critical macOS daemons (`WindowServer`, `loginwindow`, `securityd`, `opendirectoryd`, `tccd`, `Dock`, `Finder`, etc.). -4. **Sandboxed Command Execution**: Replaces raw shell execution with a strictly whitelisted runner (`dscacheutil`, `killall`, `mdutil`, `qlmanage`, `lsregister`, `csrutil`, `spctl`) with 15-second watchdog timers. - ---- - -## πŸ’» Headless CLI Companion - -MacOptimizer can be executed directly from Terminal without opening the GUI: +## Overview + +MacOptimizer Pro shows live system health (memory, swap, CPU, thermal state, disk, battery and +network), finds caches and other junk, uninstalls apps with their leftovers, finds duplicate files, +manages launch items and runs a few maintenance commands. It is a single SwiftPM package with no +third-party dependencies, and it reads system state through Darwin/Mach (`host_statistics64`, +`sysctl`, `getifaddrs`) and IOKit. + +The app is not sandboxed, because it needs to read and clean files across your home folder. It +is therefore distributed outside the Mac App Store. + +## Features + +- **Live telemetry**: memory and memory pressure, swap, CPU load, thermal state, disk space, + battery (charge, cycle count, health, temperature) and network throughput. Sampling slows down + when the window is hidden (see [docs/PERFORMANCE_REPORT.md](docs/PERFORMANCE_REPORT.md)). +- **History**: one telemetry sample per minute is stored in a local SQLite database, kept for + 48 hours and charted for the last 1, 24 or 48 hours. A list of completed operations (the last + 500) is kept in the app's preferences (UserDefaults). +- **Junk cleaner**: scans user caches, logs, browser caches, developer caches (Xcode DerivedData, + Archives and device support, simulator caches, npm, Yarn, Cargo, Gradle, pip, CocoaPods, + Homebrew, uv, Poetry), large files and app leftovers. You review a cleaning plan before + anything is removed. +- **App uninstaller**: moves an app and the leftovers you select to the Trash. Leftovers are not + selected by default. Apple system apps are refused. +- **Duplicate finder**: looks in Downloads, Documents, Pictures or Desktop and groups files by + size, then by their first 64 KB, then by a full SHA-256 hash. Duplicates you select go to the + Trash. +- **Startup items**: lists launch agents and daemons (in `~/Library` and `/Library`), enables or + disables them with `launchctl`, and can move user items to the Trash. +- **App updates**: checks the Sparkle appcasts of installed apps, `brew outdated --cask` and the + VS Code update API. Homebrew casks are upgraded by running `brew` directly, never through a + shell. +- **Maintenance**: flush the DNS cache, reset the QuickLook cache, rebuild LaunchServices, restart + CoreAudio, reindex Spotlight and clear the clipboard. Each command reports its real exit + status. Some of them need administrator rights and report a failure without them. +- **Security overview**: reads the state of System Integrity Protection (`csrutil`), Gatekeeper + (`spctl`), the application firewall (`socketfilterfw`) and whether the app has Accessibility + permission, and turns them into a 0–100 score. A state that cannot be read earns no points. +- **Watchdog**: while the app is running (also with its window closed), it checks for high memory + use, processes that stay above a CPU threshold, thermal throttling, more than 2 GB of swap and + less than 10 GB of free disk, and can send a notification. It only raises alerts and never + terminates anything by itself. It stops when you quit the app. +- **Process list**: shows the top processes and can quit or force-quit user processes (force + quit asks for confirmation). PID 0 and 1, the app itself and about 40 named system processes + are always protected. +- **Menu bar extra** with live memory, CPU, thermal and free-disk figures. +- **Command line** mode for status and cleaning (see below). +- **Languages**: English and Turkish. The app follows the macOS system language. The command line + is English only. + +## How deletion works + +Every file removal goes through one pipeline: + +1. **Scan and plan.** A scan produces a `CleaningPlan`. Each path is resolved (including symlinks) + and classified by `OperationRiskClassifier`. Protected paths never enter the plan. +2. **Preview.** The plan (items, sizes and risk) is shown for review. Nothing is removed yet. +3. **Confirmation.** Removal needs an explicit confirmation. `SafeOperationExecutor` refuses an + operation that requires confirmation when none was given. +4. **Execution.** `SafeOperationExecutor` re-checks each path right before acting and stops if it + changed after validation. Items are moved to the **Trash** by default. The executor allows + permanent removal only inside approved cache and log folders. + +Emptying the Trash is a separate action. It deletes permanently and asks for its own +confirmation. It removes Trash entries only, never the targets of symlinks inside the Trash. + +Protected locations include system roots (`/System`, `/Library`, `/usr`, `/private`, …), your home +folder itself, Desktop, Documents, Downloads, Movies, Music, Pictures, `~/Library/Keychains`, +`~/Library/Mail`, `~/Library/Preferences`, `~/.ssh`, `~/.gnupg`, `~/.aws` and `~/.config`. See +[SECURITY.md](SECURITY.md) for details. + +## AI assistant + +- **Default: local rules.** Built-in heuristics analyse the current metrics on your Mac, with no + network access. +- **Optional: NVIDIA NIM (cloud).** Off by default. It needs your own API key, and the app shows a + disclosure that you must accept before the first request. Running app names are sent only if + you also turn on the separate "Include running app names" setting. +- The API key is stored in the macOS Keychain. +- Suggested actions (scan, clean, check updates, flush DNS, terminate a process) open the normal + screen or ask for confirmation. Cleaning always goes through the plan preview. + +[PRIVACY.md](PRIVACY.md) lists exactly what is sent and every other network request the app +makes. + +## Command line + +The same binary runs headless when you pass it a command. Output is English only. ```bash -# Print instantaneous CPU, RAM, Swap, Thermal & Battery telemetry: -MacOptimizer status - -# Perform a safe Dry-Run junk scan: -MacOptimizer clean --dry-run - -# Execute Zero-Harm cleaning: -MacOptimizer clean --execute - -# Purge inactive RAM memory pages safely: -MacOptimizer purge-ram +MacOptimizer status # CPU, memory, swap, thermal, disk and battery +MacOptimizer clean # scan and print the plan (dry run, the default) +MacOptimizer clean --dry-run # same as above +MacOptimizer clean --execute --yes # move the planned items to the Trash +MacOptimizer clean --execute --yes --include-trash # also permanently empty the Trash +MacOptimizer version +MacOptimizer help ``` ---- - -## πŸ€– Multi-Provider AI Platform - -Choose the intelligence provider that matches your privacy and performance needs: - -| Provider | Privacy & Network | Capabilities | -| :--- | :--- | :--- | -| **Local Heuristics** | 100% Offline β€’ Zero Network | Instant rule-based memory, CPU bottleneck, and junk diagnosis. | -| **Ollama Local** | 100% Offline β€’ Localhost Only | On-device local LLM reasoning (Llama 3.2, DeepSeek-R1:8B) via `localhost:11434`. | -| **NVIDIA NIM** | Cloud HTTPS API | Enterprise-scale diagnostic reasoning with Llama 3.3 70B and DeepSeek R1. | -| **OpenAI-Compatible** | Custom Endpoint | Connect to your self-hosted vLLM, LM Studio, or OpenAI servers. | - ---- - -## 🏎️ Performance Benchmarks +`--execute` without `--yes` is refused. The Trash is left alone unless you pass +`--include-trash`. -*Tested on MacBook Pro 14" (Apple M4 Pro, 24 GB RAM, macOS 15.0)*: +## Installation -* **Mach-O Header Detection**: **0.04 ms** (vs ~4.8 ms with `lipo` β€” **~120x faster**). -* **Mach VM Telemetry Read**: **< 0.02 ms** (vs ~45 ms with `ps` / `top`). -* **Multi-Category Parallel Scan**: **0.42 s** for 50,000 files using Swift `TaskGroup`. -* **SHA-256 Duplicate Streaming**: **1.2 GB/s** using Apple CryptoKit streaming. -* **Watchdog Background CPU Load**: **~0.01%** (zero impact on battery life). +### Download a release -For full benchmark specifications, see [BENCHMARKS.md](BENCHMARKS.md). +Signed and notarized DMGs start with **v3.1.0**, which is being prepared now. Earlier releases +(v2.1.0–v3.0.0) were not notarized and contain known safety defects. Do not use them. ---- - -## πŸ“₯ Installation +### Build from source -### Option 1: Download Release -Download the notarized `MacOptimizer.dmg` from the [Releases](https://github.com/Codifya/MacOptimizer/releases) page and drag it to `/Applications`. +You need macOS 14 or later and a Swift 6 toolchain (Xcode 16 or later; CI uses Xcode 16.4). -### Option 2: Build from Source ```bash -# Clone the repository git clone https://github.com/Codifya/MacOptimizer.git cd MacOptimizer -# Run unit tests (36 suites / 200+ assertions) -swift test - -# Build release .app bundle -./Scripts/build_app.sh +swift test # run the test suite +./Scripts/build_app.sh # build MacOptimizer.app (unsigned) ``` ---- +The test suite has 87 XCTest test methods. It is hermetic: tests use temporary directories, a +fake home folder, injected command runners and a throwaway Keychain item, so running them does +not change your Mac. CI runs the whole suite on every pull request. + +## Documentation + +- [ARCHITECTURE.md](ARCHITECTURE.md): how the code is organised +- [SECURITY.md](SECURITY.md): safety model and how to report a vulnerability +- [PRIVACY.md](PRIVACY.md): what stays on your Mac and what is sent over the network +- [CHANGELOG.md](CHANGELOG.md) and [ROADMAP.md](ROADMAP.md) +- [BENCHMARKS.md](BENCHMARKS.md) and [docs/PERFORMANCE_REPORT.md](docs/PERFORMANCE_REPORT.md) +- [docs/LOCALIZATION.md](docs/LOCALIZATION.md): adding or changing translations + +## Contributing + +Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md). -## πŸ“„ License +## License -MacOptimizer is released under the [Apache License 2.0](LICENSE). -Created and maintained with ❀️ by [Codifya](https://github.com/Codifya). +MacOptimizer Pro is released under the [Apache License 2.0](LICENSE). +Maintained by [Codifya](https://github.com/Codifya). diff --git a/ROADMAP.md b/ROADMAP.md index 8f730ce..cefca99 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,50 +1,43 @@ -# πŸ—ΊοΈ MacOptimizer Pro Roadmap - -This roadmap outlines the past milestones and future evolution of MacOptimizer Pro toward version 3.0+. - ---- - -## 🎯 Release Milestones - -### `v2.0 β€” Production Native Core (Completed)` -- [x] Native SwiftUI Liquid Glass user interface. -- [x] Darwin Mach kernel telemetry (`host_statistics64`, `sysctlbyname`). -- [x] Microsecond-level binary Mach-O architecture detector. -- [x] Concurrent multi-category junk scanner with `TaskGroup`. -- [x] Deep app uninstaller & orphan cache detector. -- [x] Sparkle RSS and Homebrew update checker. -- [x] 7/24 Autonomous background watchdog. -- [x] NVIDIA NIM cloud AI Copilot integration. -- [x] Fully responsive layout for 13" laptops to 5K monitors. - ---- - -### `v2.1 β€” Security Hardening & Open Source Ready (Completed)` -- [x] **Zero-Harm Policy Engine**: Modular `PathProtectionPolicy`, `ProcessProtectionPolicy`, `ApplicationProtectionPolicy`, and `LaunchItemProtectionPolicy`. -- [x] **Symlink Traversal Attack Protection**: Path canonicalization using `URL.resolvingSymlinksInPath()`. -- [x] **Operation Risk Classification**: `.safe`, `.low`, `.medium`, `.destructive`, and `.forbidden` classification. -- [x] **Dry-Run Plan Engine**: `CleaningPlan` preview lifecycle before any disk modifications. -- [x] **Keychain Secret Management**: Encrypted API key storage via macOS `Security.framework`. -- [x] **Sandboxed Command Runner**: Whitelisted binaries only with 15s watchdog timeout. -- [x] **Multi-Provider AI Platform**: Decoupled `AIProvider` supporting Local Heuristics, Ollama, NVIDIA NIM, and OpenAI endpoints. -- [x] **Telemetry Store**: Embedded SQLite database with WAL mode for time-series metrics. -- [x] **Massive Test Suite**: 23+ unit test suites with 120+ assertions passing. -- [x] **Open Source Guidelines**: Apache-2.0 License, `SECURITY.md` with STRIDE model, `CONTRIBUTING.md`, `ARCHITECTURE.md`, and `PRIVACY.md`. - ---- - -### `v2.2 β€” Observability Charts & Advanced Telemetry (Upcoming)` -- [ ] Swift Charts integration for 1h, 24h, 7d, and 30d historical telemetry graphs. -- [ ] Thermal throttling and fan speed monitoring via IOKit. -- [ ] Network bandwidth per-process monitor. -- [ ] Disk IO read/write throughput metrics. - ---- - -### `v3.0 β€” Production Distribution & Enterprise Pipeline (Target)` -- [ ] Automated GitHub Actions release pipeline with Apple Developer ID code signing. -- [ ] Apple Notarization via `xcrun notarytool` and ticket stapling. -- [ ] Compressed DMG installer generation. -- [ ] SPDX Software Bill of Materials (SBOM) generation. -- [ ] GitHub Artifact Attestation for verifiable supply-chain security. -- [ ] Modular plugin & custom automation rule engine. +# Roadmap + +This roadmap lists what is done and what comes next. Items move to done only when they are +merged and covered by the test suite or verified on macOS. + +## History + +v2.1.0 to v3.0.0 were published on 2026-08-28. They added the features the app still has +(telemetry, junk cleaner, uninstaller, duplicate finder, startup items, update checks, security +overview, watchdog, AI assistant, CLI), but a later audit found serious defects in them: a command +injection in the update screen, deletion paths without preview or confirmation, results reported +as successful when commands failed, and documentation that claimed more than the code did. Do not +use those releases. + +## v3.1.0 β€” Safety release (in progress) + +Done (merged to `main`): + +- [x] Command injection removed: no shell execution; Homebrew runs directly with a validated token. +- [x] One deletion pipeline: plan preview, enforced confirmation, re-validation, Trash by default. +- [x] Honest results: real exit codes, RAM purge removed, security score without free points, + fixed battery health formula, no invented chart data. +- [x] AI assistant: local heuristics by default; NVIDIA NIM only after a disclosure; app names + only with a separate opt-in; unused providers removed. +- [x] Monitoring, process execution and scanner hardening (bounded memory, no pipe deadlocks, + cancellable parallel scans, telemetry history recorded). +- [x] Hermetic test suite run in full by CI on macOS with Swift 6. +- [x] English and Turkish localization, following the system language. +- [x] Documentation aligned with the code. + +Remaining: + +- [ ] One version source for the app, the CLI and the release tag. +- [ ] Developer ID signing, hardened runtime, notarization and stapling of the DMG. + +## Later (not scheduled) + +- Split `AppState` into smaller feature models and inject services. +- Merge `Helpers/SafetyGuard` into the `Core/Security` policies. +- App icon, and applying the menu bar extra setting. +- Verify Homebrew update detection against current `brew` JSON output. +- Instruments measurements for the figures still marked `REQUIRES_INSTRUMENTS_VALIDATION` in + [docs/PERFORMANCE_BASELINE.md](docs/PERFORMANCE_BASELINE.md). diff --git a/SECURITY.md b/SECURITY.md index b40a52e..658b06b 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,66 +1,103 @@ -# πŸ›‘οΈ Security Policy & Zero-Harm Architecture - -MacOptimizer is designed from the ground up as a **security-first, defense-in-depth macOS system health and optimization toolkit**. We believe that any software interacting with system resources, memory, and storage must adhere to the highest standard of safety, transparency, and auditability. - ---- - -## πŸ”’ Zero-Harm Architecture (Defense-in-Depth) - -MacOptimizer enforces multiple layers of validation before any filesystem, process, or maintenance action is executed: - -```mermaid -graph TD - Trigger["Action Proposal (User or AI)"] --> Risk["OperationRiskClassifier"] - Risk --> Policy["SafetyPolicyEngine"] - Policy --> Symlink["Symlink & Path Canonicalization"] - Symlink --> DryRun["Dry-Run Preview (CleaningPlan)"] - DryRun --> UserConfirm["Explicit User Confirmation"] - UserConfirm --> SafeExec["SafeOperationExecutor (Atomic & Trash-Protected)"] - SafeExec --> Audit["Encrypted/WAL Audit Log (SQLite)"] -``` - -### 1. Strict Path Protection & Anti-Data Loss -* **System Roots Protection**: Hardcoded boundaries preventing any deletion or write inside `/`, `/System`, `/System/Applications`, `/System/Library`, `/Library`, `/usr`, `/bin`, `/sbin`, `/var`, `/etc`, `/dev`, `/private`, `/Volumes`, `/cores`, `/opt`. -* **User Data Protection**: Strict guards around user root directories (`~`, `~/Desktop`, `~/Documents`, `~/Downloads`, `~/Movies`, `~/Music`, `~/Pictures`, `~/Library`, `~/Library/Keychains`, `~/Library/Mail`, `~/.ssh`, `~/.gnupg`, `~/.aws`, `~/.config`). -* **Symlink Attack Resistance**: All paths are resolved to their canonical destination using `URL.resolvingSymlinksInPath()` prior to evaluating safety policies, neutralizing symlink-based traversal attacks. -* **Safe Removal Fallback**: Non-cache items are moved to the user's macOS Trash (`FileManager.trashItem`) rather than being unlinked directly. - -### 2. Process Termination Protection (Anti-Kernel Panic) -* **Kernel & Init Guards**: Hard protection for PID 0 (`kernel_task`), PID 1 (`launchd`), and MacOptimizer's own process. -* **macOS System Daemons Whitelist**: 35+ critical background processes (`WindowServer`, `loginwindow`, `diskarbitrationd`, `securityd`, `opendirectoryd`, `coreauthd`, `syspolicyd`, `tccd`, `trustd`, `Dock`, `Finder`, `SystemUIServer`, `ControlCenter`, `mds`, `powerd`, etc.) cannot be killed under any circumstances. - -### 3. Sandboxed Command Execution -* No arbitrary shell string execution (`/bin/sh` or `/bin/zsh`). -* Whitelisted binaries only (`ApprovedExecutable`: `dscacheutil`, `killall`, `mdutil`, `qlmanage`). -* 15-second watchdog timer automatically terminates hanging child processes. - -### 4. Secret & API Key Management -* Cloud AI credentials (e.g. NVIDIA NIM API keys, custom tokens) are stored exclusively in the **macOS Keychain** (`Security.framework` with `kSecAttrAccessibleWhenUnlockedThisDeviceOnly`). -* Secrets are never logged, never saved in plaintext `UserDefaults`, and excluded from bug reports. - ---- - -## 🎯 STRIDE Threat Model - -| Threat Category | Potential Attack Vector | Mitigation in MacOptimizer | -| :--- | :--- | :--- | -| **Spoofing** | Rogue processes impersonating legitimate apps | Binary Mach-O header verification and code signing check. | -| **Tampering** | Symlinks pointing from cache dirs to user documents | `URL.resolvingSymlinksInPath()` canonical path verification. | -| **Repudiation** | Unverified file or process actions | Strict audit logging in WAL-mode SQLite database. | -| **Information Disclosure** | Cloud AI exfiltrating private files | System prompts only include anonymous hardware counters. System data never leaves device without explicit user action. | -| **Denial of Service** | Purging active system memory or killing WindowServer | `ProcessProtectionPolicy` and safe memory clamped limits (`64 MB - 256 MB`). | -| **Elevation of Privilege** | Sudo escalation via unapproved commands | `SandboxedCommandRunner` strictly whitelists safe macOS utilities without root requirements. | - ---- - -## 🚨 Reporting a Vulnerability - -We welcome responsible security disclosures. If you discover a security vulnerability in MacOptimizer: - -1. **Do NOT open a public GitHub issue.** -2. Send a detailed report via email to: **security@osmancagrigenc.dev** (or submit via [GitHub Private Vulnerability Reporting](https://github.com/osmancagrigenc/MacOsOptimizer/security/advisories/new)). -3. Include: - * Description of the vulnerability and affected versions. - * Step-by-step reproduction steps or proof-of-concept. - * Potential impact. -4. We will acknowledge receipt within 48 hours and provide an estimated remediation timeline. +# Security Policy + +MacOptimizer Pro deletes files, terminates processes and runs system commands, so its safety +rules matter. This document describes what the code actually enforces and how to report a +problem. + +## Supported versions + +| Version | Status | +| --- | --- | +| 3.1.0 and later | Supported. v3.1.0 is being prepared and will be the first Developer ID-signed and notarized release. | +| 2.1.0 – 3.0.0 | **Not safe. Do not use.** These releases contain known safety defects: a command injection in the update screen, and deletion paths that skipped the preview and confirmation. They were ad-hoc signed and not notarized. | + +## Deletion pipeline + +Every file removal in the app and the CLI goes through `SafeOperationExecutor`: + +1. **Plan and preview.** Scans produce a `CleaningPlan`. Paths are canonicalised with + `URL.resolvingSymlinksInPath()` and classified by `OperationRiskClassifier`; forbidden paths + are never added. The plan is shown before anything is removed. The CLI prints it and needs + `--execute --yes`. +2. **Confirmation is enforced.** `SafetyPolicyEngine` returns `allowed`, `requiresConfirmation` or + `denied`. The executor throws when a `requiresConfirmation` decision arrives without a + confirmation, and always refuses `denied`. +3. **Re-validation.** Right before acting, the executor resolves the path again and stops if it + no longer resolves to the validated location or has become forbidden. +4. **Trash by default.** The app's cleaners move items to the Trash. The executor permits + permanent removal only inside approved cache and log folders (for example + `~/Library/Caches/`, `~/Library/Logs/`, Xcode DerivedData, npm/Yarn/Cargo/Gradle/pip caches). +5. **Emptying the Trash** is a separate, permanent action with its own confirmation (in the CLI, + `--include-trash`). It removes only entries directly inside `~/.Trash` and never follows + symlinks to their targets. + +### Protected paths + +`PathProtectionPolicy` forbids: + +- system locations: `/`, `/System`, `/Library` (except `/Library/Caches/` and + `/Library/Logs/DiagnosticReports/`), `/usr`, `/bin`, `/sbin`, `/var`, `/etc`, `/dev`, + `/private`, `/Volumes`, `/cores`, `/opt`, and `/Users` outside your own home folder; +- in your home folder: the folder itself, Desktop, Documents, Downloads, Movies, Music, Pictures, + Applications, `Library`, `Library/Application Support`, `Library/Keychains`, `Library/Mail`, + `Library/Messages`, `Library/Photos`, `Library/Safari`, `Library/Preferences`, + `Library/Containers`, `Library/Group Containers`, `Library/LaunchAgents`, + `Library/Mobile Documents`, shell and Git configuration files, and everything under `.ssh`, + `.gnupg`, `.aws`, `.config` and `.git`. + +The exact lists are in `Sources/MacOptimizer/Core/Security/PathProtectionPolicy.swift`. + +## Process termination + +Force-quitting from the Memory screen and terminating a process suggested by the AI assistant +ask for confirmation first. The quit button in the dashboard's top-process card sends a normal +quit request (the app's terminate, or SIGTERM) without a separate prompt. PID 0 (`kernel_task`), PID 1 +(`launchd`), the app's own process, a list of about 40 system processes (`WindowServer`, +`loginwindow`, `securityd`, `tccd`, `Dock`, `Finder`, `mds`, `powerd`, …) and executables under +`/System/Library/CoreServices/`, `/usr/libexec/` and `/System/Library/Frameworks/` cannot be +terminated. The watchdog never terminates processes on its own. + +## Command execution + +- There is no shell execution (`/bin/sh -c`, `zsh -c`) anywhere in the app. +- System tools run through `SandboxedCommandRunner`, which accepts only an allow-list of absolute + executable paths (`dscacheutil`, `killall`, `mdutil`, `qlmanage`, `lsregister`, `atsutil`, + `launchctl`, `csrutil`, `spctl`, `defaults`, `socketfilterfw`), drops arguments that contain + `;`, `|`, `&`, `` ` `` or `$`, and times out after 15 seconds by default. +- `/bin/ps`, `/bin/kill` and `brew` run as a fixed executable with an argument array. Homebrew + upgrades accept only a validated cask token (`[a-z0-9@._+-]`); data from remote appcasts is + never used as a command. Links from appcasts are opened only for `http` and `https` URLs. +- All child processes go through `ProcessExecutor`: output is drained while the child runs and + capped, and a timed-out child gets SIGTERM and then SIGKILL. + +## Secrets + +The NVIDIA NIM API key is stored in the macOS Keychain +(`kSecAttrAccessibleWhenUnlockedThisDeviceOnly`). The copy of the AI configuration kept in +UserDefaults has an empty key field. A key saved in UserDefaults by an older version is migrated +to the Keychain. + +## Threat model summary + +| Threat | Mitigation in the code | Limits | +| --- | --- | --- | +| Deleting the wrong files | Path policy, plan preview, enforced confirmation, Trash by default | The Trash itself is emptied permanently when you confirm it | +| Symlink swaps between check and use | Canonicalisation, then re-validation right before acting | A narrow race between the last check and the file operation remains | +| Command injection | No shell; allow-listed executables; argument filtering; validated Homebrew tokens | β€” | +| Killing critical processes | PID and name/path protection lists; confirmation for force quit and AI suggestions | Name lists are maintained by hand | +| Data sent to the cloud | NVIDIA NIM is off by default and needs a disclosure; app names need a separate opt-in | See [PRIVACY.md](PRIVACY.md) for exactly what is sent | +| Tampered downloads | From v3.1.0: Developer ID signature and notarization (in preparation), plus GitHub build-provenance attestation | Releases up to v3.0.0 were not notarized | + +The app is not sandboxed and has no privileged helper. It runs with your user's permissions only. +There is no audit log of file operations; the History screen lists completed operations from +UserDefaults. + +## Reporting a vulnerability + +Please do not open a public issue for security problems. + +1. Email **security@osmancagrigenc.dev** with a description, the affected version, steps to + reproduce and the impact you expect. +2. We aim to acknowledge reports within 48 hours and to agree on a fix timeline with you. + +Repository: https://github.com/Codifya/MacOptimizer diff --git a/docs/LOCALIZATION.md b/docs/LOCALIZATION.md index fcea5c4..0a3650c 100644 --- a/docs/LOCALIZATION.md +++ b/docs/LOCALIZATION.md @@ -1,5 +1,8 @@ # Localization +The app ships in English and Turkish and follows the macOS system language (English is the +fallback). CLI output is English only and does not use these tables. + Add each key and translation to the area's table in `Sources/MacOptimizer/Resources/en.lproj/.strings` and `Sources/MacOptimizer/Resources/tr.lproj/
.strings`. Keep English as the key/source value; use diff --git a/docs/PERFORMANCE_BASELINE.md b/docs/PERFORMANCE_BASELINE.md index f801b2c..bd0b285 100644 --- a/docs/PERFORMANCE_BASELINE.md +++ b/docs/PERFORMANCE_BASELINE.md @@ -3,6 +3,10 @@ Baseline for the performance, memory and concurrency hardening pass. It is taken at commit `35dacca` (MacOptimizer Pro 3.0.0), before any change. +> **Status note:** the "Before" data describes v3.0.0 and is kept as a historical record. Some +> features mentioned here, such as RAM purge, were removed later. See +> [PERFORMANCE_REPORT.md](PERFORMANCE_REPORT.md) for the current state. + ## How this baseline was established This pass was carried out in a Linux container, not on a Mac. That limits what can be measured: diff --git a/docs/PERFORMANCE_REPORT.md b/docs/PERFORMANCE_REPORT.md index 5a1daf2..2e428e2 100644 --- a/docs/PERFORMANCE_REPORT.md +++ b/docs/PERFORMANCE_REPORT.md @@ -3,6 +3,11 @@ Companion to [`PERFORMANCE_BASELINE.md`](PERFORMANCE_BASELINE.md), which has the method and the "before" data. +> **Status note:** this report was written for the hardening pull request (#1), which was prepared +> on Linux. That pull request was later built and tested on macOS before it was merged, and CI now +> runs the full suite on macOS. Later changes are reflected in the "Remaining risks" section: RAM +> purge was removed (#5) and the first CPU sample no longer uses a placeholder (#5). + **Evidence levels used below** - **Measured**: executed with Swift 6.0.3 on Linux against the shipping source files. @@ -173,7 +178,7 @@ main actor wait synchronously on background work: every bridge is an `async` con quick actions do not. - In the sidebar, only `SidebarMemoryBadge` and `SidebarAvailableMemoryText` observe metrics. The navigation `List` no longer rebuilds every 2.5 s. -- `MenuBarView` observes `LiveMetricsStore` for metrics and `AppState` for purge and watchdog state. +- `MenuBarView` observes `LiveMetricsStore` for metrics and `AppState` for app state. - Screens that show no metrics (Settings, App Manager, Junk Cleaner, Startup, Security, History, Updates, AI) no longer re-evaluate on metrics ticks. That removes, for example, the App Manager's per-tick filter and sort over all installed apps. @@ -228,24 +233,26 @@ main actor wait synchronously on background work: every bridge is an `async` con - Swift 6 language-mode typecheck of every non-UI source file (with Linux shims for AppKit, IOKit and CryptoKit symbols) is clean. - **Not run here**: the XCTest suite and the SwiftUI/AppKit targets need macOS. CI - (`.github/workflows/ci.yml`, macos-14) runs `swift build` and `swift test`. + (`.github/workflows/ci.yml`, now macos-15 with Xcode 16.4) runs `swift build` and `swift test`. ## Remaining risks 1. **No macOS build was performed in this environment.** The SwiftUI and AppKit files (`AppState`, the views, `SystemMonitorService`, `TelemetryStore`, `AppIconView`) were only - syntax-checked. Typecheck failures, if any, will surface in CI. + syntax-checked here. (Resolved: the pull request was built and tested on macOS before merge, + and CI builds it on macOS.) 2. `ps` is still spawned while a process screen is visible (every 7.5 s). A `libproc` (`proc_listallpids`, `proc_pid_rusage`) implementation would remove the spawn, but it cannot read RSS or CPU of root-owned processes (for example `WindowServer`) without privileges, whereas setuid `ps` can. Revisit only with a privileged helper. -3. The first CPU sample still reports a placeholder (15 %) until a delta exists (unchanged behaviour). +3. The first CPU sample reported a placeholder (15 %) until a delta existed. (Resolved in #5: CPU + usage now needs two real samples.) 4. Visibility is app-level occlusion. A visible but fully covered main window counts as hidden, which is intended. -5. `MemoryOptimizerService.purgeMemory` still allocates and touches up to 256 MB by design. That is - product behaviour, not a leak. -6. `BENCHMARKS.md` numbers predate this pass and were not reproducible from the code. For example, - the junk walk was serialised on an actor, not parallel. +5. `MemoryOptimizerService.purgeMemory` allocated and touched up to 256 MB by design. (Resolved in + #5: RAM purge was removed.) +6. `BENCHMARKS.md` numbers predated this pass and were not reproducible from the code. For example, + the junk walk was serialised on an actor, not parallel. (Resolved: the numbers were removed.) ## Recommended Instruments runs