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
2 changes: 1 addition & 1 deletion PRIVACY.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Keydoze has no accounts, advertising, analytics, or remote logging. Cleaning ses
Keydoze uses [Sparkle](https://sparkle-project.org), an open-source update framework, to keep itself current.

- **When:** when you open Keydoze if the last check was more than a day ago, then once a day while it stays open. No check starts during a cleaning session.
- **What it requests:** one file, `appcast.xml`, from Keydoze's [GitHub releases](https://github.com/dlev02/Keydoze/releases). It downloads an update only after you choose **Install Update**.
- **What it requests:** one file, `appcast.xml`, from Keydoze's [GitHub releases](https://github.com/dlev02/Keydoze/releases). It downloads an update only after you choose **Install Update**. Both come from `github.com`, which redirects to `release-assets.githubusercontent.com`. If you use a firewall app, these are the hosts to allow.
- **What GitHub can see:** as with any web request, your IP address and the time, plus the app's name and version and Sparkle's version (for example `Keydoze/0.2.0 Sparkle/2.10.1`) and your Mac's language preference. GitHub handles this under [its privacy statement](https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement).
- **What is not sent:** typed input, input events, your session history, device identifiers, or a hardware or system profile.
- **What the developer can see:** GitHub shows repository owners a running total of downloads for each release file. Checks add to the total for `appcast.xml`. It does not show who made them.
Expand Down
4 changes: 2 additions & 2 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

## Current distribution status

On 21 October 2026, version 0.1.0 build 3 was signed with **Developer ID Application: Brandon Stellina (7BVMD7TA97)**, hardened runtime, and a secure timestamp, then accepted by Apple notarization (submission `00f9d568-15b8-4d7a-bd2e-89b8443a1925`). The ticket was stapled and validated, and Gatekeeper reports `source=Notarized Developer ID`. The notarized app is published in the `v0.1.0` GitHub release as a DMG with a drag-to-Applications window (SHA-256 `e9a53f3a9174363823e9494d178624a4083c54d122fbdabf098f8ee4597127bf`, notarization submission `679c1732-cae7-4837-a395-7ebc9cd72062`) and as a ZIP (SHA-256 `56ca0ca17a17605724b0de926351a42b23c225abd594b1248e55dc46e59321e3`).
On 5 November 2026, version 0.2.0 build 4 was published as the `v0.2.0` GitHub release from commit `bdea69d`. It is signed with **Developer ID Application: Brandon Stellina (7BVMD7TA97)**, hardened runtime, and secure timestamps, including Sparkle's helpers. Apple accepted the app (submission `2b4a9fbe-64a7-41ae-8d33-2aaf835e95c2`) and the DMG (submission `cc82d4a3-333e-497c-aa60-9afcdc642b87`). Both tickets are stapled, and Gatekeeper reports `source=Notarized Developer ID`. Checksums are attached to the release: DMG SHA-256 `d7d0deae9a1afb359d2903ffcb72798bbb0e2fa31a6e5c5100949d2e9ba42888`, ZIP SHA-256 `a6f03b52a5b7a659001568cf3a8496dcdddc3cba9e41eaf959bca2f33c99bbb4`.

Earlier submissions under the previous team (`M379WPVT8A`, whose Developer ID certificate was revoked) are superseded. Notarization uses an App Store Connect team API key stored in the system keychain through `asc auth login`; no credentials are stored in this repository. To check a submission:

```sh
asc notarization status --id 00f9d568-15b8-4d7a-bd2e-89b8443a1925 --output json
asc notarization status --id 2b4a9fbe-64a7-41ae-8d33-2aaf835e95c2 --output json
```

After Apple reports **Accepted**, staple and validate the ticket, verify Gatekeeper acceptance, and package that stapled app for the public release. If Apple rejects it, inspect `asc notarization log --id SUBMISSION_ID` and resolve the reported issue first.
Expand Down
9 changes: 6 additions & 3 deletions docs/VALIDATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Recorded 6 September 2026. Compatibility target: macOS 26+. Actual environment:

## Observed results

- **Distribution signing and notarization — 5 November 2026:** Version 0.2.0 build 4 was built from `bdea69d` by `script/make_release.sh`. Strict verification passed for the app and Sparkle's framework, `Autoupdate` and `Updater.app`, all with Developer ID, hardened runtime and a secure timestamp. Apple accepted the app and DMG, both tickets stapled and validated, and `spctl` reported `Notarized Developer ID`. See [RELEASING.md](RELEASING.md) for submission IDs and checksums.
- **Distribution signing and notarization — 21 October 2026:** Version 0.1.0 build 3 was signed as a separate optimized Apple-silicon copy with Developer ID Application for team `7BVMD7TA97`, hardened runtime, and a secure timestamp. Strict verification passed. Apple accepted notarization submission `00f9d568-15b8-4d7a-bd2e-89b8443a1925`; the ticket stapled and validated, and `spctl` reported `Notarized Developer ID`. Earlier submissions under team `M379WPVT8A` are superseded. The stable development app was preserved.

- **User-reported physical laptop test — 6 September 2026:** Drew tested Keydoze on his laptop and confirmed that it fully worked with the hardware. This confirms the overall cleaning workflow on that laptop. The report did not enumerate individual keys, gestures, external devices, or interruption scenarios; the detailed coverage rows below distinguish those unrecorded cases from the overall hardware confirmation.
Expand All @@ -22,7 +23,7 @@ Local debug evidence is under ignored `docs/evidence/`; it contains lifecycle st

## Updates (Sparkle)

Recorded 5 November 2026, on Apple silicon with macOS 27. Checks used throwaway Developer ID signed copies, a throwaway Ed25519 key and a local feed. Sparkle's `SU*` defaults were removed afterwards.
Recorded 5 November 2026, on Apple silicon with macOS 27. Unless noted, checks used throwaway Developer ID signed copies, a throwaway Ed25519 key and a local feed. Sparkle's `SU*` defaults were removed afterwards.

- **Full update:** a 0.1.8 copy found 0.1.9 at launch, showed the release notes, then on **Install Update** and **Install and Relaunch** downloaded, verified the EdDSA signature, replaced itself and relaunched as 0.1.9 under a new process, with a valid signature.
- **What was sent:** the local server recorded `GET /appcast.xml` with `User-Agent: Keydoze/0.1.8 Sparkle/2.10.1` and the headers `Host`, `Accept`, `Accept-Language`, `Connection` and `Accept-Encoding`. There was no query string, cookie or system profile.
Expand All @@ -33,8 +34,10 @@ Recorded 5 November 2026, on Apple silicon with macOS 27. Checks used throwaway
- **Session, real tap:** one keyboard-only `--live-check` session with the external watchdog armed, tap installed from 5.4 s to 13.65 s. An update response arrived during it. No Sparkle window appeared, the process did not change, and the session ended normally with `timedOut` and no tap.

- **Run from a disk image:** a copy opened from a read-only volume, with an update available, offered no update and logged that it can't update from a read-only location.
- **Published release:** the DMG, ZIP, `appcast.xml` and their checksums were downloaded from GitHub into a clean folder and matched. The published appcast's EdDSA signature verified in the app against the real `SUPublicEDKey`. A 0.1.9 test copy with that key then updated to the ZIP downloaded from the release, served from a local feed, and relaunched as a stapled, notarized 0.2.0. The ZIP's signature in that feed matched the published appcast.
- **Feed unreachable:** on the test Mac a firewall app held the connection to GitHub. The automatic check timed out after 60 seconds with no window, and the app kept working.

Not tested: an update while offline or on a slow network beyond a delayed feed, a copy in a folder the user can't write to, and a translocated copy.
Not tested: the app itself fetching the feed and the update from GitHub, which that firewall held on the test Mac (`curl` fetched both); a copy in a folder the user can't write to; a translocated copy.

## UI checks on the packaged native app

Expand Down Expand Up @@ -86,4 +89,4 @@ plutil -lint 'dist/Keydoze.app/Contents/Info.plist'

The default local release is development signed. The separate Developer ID distribution copy is notarized and stapled, and each published release records that in [RELEASING.md](RELEASING.md). The repository contains no production service, credentials or privileged helper. The only network use is Sparkle's update checks and downloads.

The final archive checksum is recorded beside the local package in `dist/Keydoze-0.1.0-local-arm64.zip.sha256`. Generated bundles and local diagnostics are excluded from source control.
Release checksums are attached to each GitHub release. Generated bundles and local diagnostics are excluded from source control.
Binary file added docs/design/settings-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/design/update-window.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading