docs: record v100.0.1 release, brew tap, Sparkle key wiring + build gotcha
This commit is contained in:
2 files changed
+27
-33
No files matched your search
@@ -228,9 +228,12 @@ per-component owner actions gathered from the scaffolding agents merged in.
|
||||
notarization/Gatekeeper. Also re-sign the vendored Sparkle helpers under the SAME Developer ID
|
||||
(PLAN §3.3 / §4.6) or notarization rejects. (This is also what makes the default `ai/build.sh`
|
||||
stop failing on the missing `Local Self-Signed` cert.)
|
||||
- [ ] **Generate a FRESH Sparkle EdDSA keypair:** paste the PUBLIC key into `Info.plist:66`
|
||||
(replace `REPLACE_WITH_FORK_SUPUBLIC_EDKEY`); store the PRIVATE key as the CI secret
|
||||
`SPARKLE_ED_PRIVATE_KEY`. The placeholder is NOT lwouis's key and will verify nothing.
|
||||
- [x] **Sparkle EdDSA keypair generated (2026-06-15).** PUBLIC key wired into `Info.plist`
|
||||
(`SUPublicEDKey`); PRIVATE key stored in 1Password "CommandTabFree-Sparkle-EdDSA" + GitHub
|
||||
Actions secret `SPARKLE_ED_PRIVATE_KEY` (env `production`); keychain account `commandtabfree`.
|
||||
`SUEnableAutomaticChecks` set false until DOMAIN serves a real appcast.
|
||||
**TODO at CI-wiring time:** `update_appcast.sh` still calls the deprecated `sign_update -s` —
|
||||
switch it to `--ed-key-file` (or `--account commandtabfree`); the `-s` path rejects this key format.
|
||||
|
||||
### 3.4 GitHub Actions secrets + Environment (BLOCKING for release)
|
||||
|
||||
|
||||
+21
-30
@@ -1,39 +1,30 @@
|
||||
# SESSION-STATE — CommandTabFree (de-paywalled AltTab fork)
|
||||
|
||||
_Handoff written 2026-06-15. Branch: `depaywall-free` (NOT merged to master)._
|
||||
_Updated 2026-06-15. `master` now carries the fork (merged + pushed). Public pre-release **v100.0.1** live; Homebrew tap live._
|
||||
|
||||
## What this is
|
||||
`KofTwentyTwo/alt-tab-free` is a fork of **AltTab** (`lwouis/alt-tab-macos`, GPL-3.0). Upstream author lwouis added a Pro paywall in v11.0.0 (commit `9147a4a8`); this fork **neutralizes the paywall so all features are free** and is rebranded **CommandTabFree**. Goal: ship free + keep merging upstream forever (thin, merge-stable patch — see `docs/PLAN-maintained-fork.md`).
|
||||
`KofTwentyTwo/alt-tab-free` is a fork of **AltTab** (`lwouis/alt-tab-macos`, GPL-3.0) that neutralizes the v11 Pro paywall so all features are free, rebranded **CommandTabFree**. Strategy: thin, merge-stable patch tracking upstream forever (`docs/PLAN-maintained-fork.md`).
|
||||
|
||||
## ✅ DONE (all on branch `depaywall-free`, HEAD `98a023aa`)
|
||||
- **De-paywall** (commit `f3d76859`): 3 inert edits — `LicenseManager.computeState()` → `guard false else { return .pro }` (single state producer opens every gate); `LicenseCookie.syncLicenseCookie` + `AppCenterCrash.init` wrapped `if false`; `App.handleCustomUrl` early-returns (kills activate-fingerprint POST). `src/pro/` left physically present but inert.
|
||||
- **Anti-relock tests** (`4506c539`, `1a914c88`): `testDepaywall*` guards in `LicenseManagerTests.swift`; 16 legacy paywall tests `XCTSkip`-marked. **Test scheme GREEN.**
|
||||
- **Identity** (`4d82a684`): `PRODUCT_NAME=CommandTabFree`, `PRODUCT_BUNDLE_IDENTIFIER=com.koftwentytwo.commandtabfree` (FROZEN) in `config/local.xcconfig`.
|
||||
- **Local-build version fix** (`e2429096`): `CURRENT_PROJECT_VERSION=0.0.0` in `local.xcconfig` (else `App.version` (App.swift:14) nil-crashes on local builds).
|
||||
- **Brand sweep + About** (`f5f9034d`): 11 user-facing "AltTab"→"CommandTabFree"; About box credits upstream — _"A free fork of AltTab by Louis Pontoise — GPL-3.0"_ (`AboutTab.swift:18`), Source-code link → fork repo (`App.repository`, App.swift:16). PRESERVED: migration key `PreferencesMigrations.swift:363` "Screen showing AltTab", LICENCE/NOTICE/contributors, src/pro strings.
|
||||
- **Placeholder icon** (`98a023aa`): `resources/icons/app/app.icns` = dark slate + ⌘⇥ glyph (generated; **real artwork still TODO**). Xcode scheme product name fixed → `CommandTabFree.app`.
|
||||
- **Local build runs**: ad-hoc-signed `CommandTabFree.app`, de-paywalled, launches. CI/identity scaffolding (`upstream_sync.yml`, `guard.yml`, adapted `ci_cd.yml`, `update_appcast.sh`) committed earlier (`3dde8a91`).
|
||||
## ✅ DONE
|
||||
- De-paywall + anti-relock tests + frozen identity (`com.koftwentytwo.commandtabfree`) + brand sweep + placeholder icon — all on **`master`** (was `depaywall-free`, fast-forward merged, HEAD `c7d2d968`, pushed to origin; source is public for GPL §6).
|
||||
- **Sparkle EdDSA keypair generated.** Public key in `Info.plist` (`SUPublicEDKey`); private key in 1Password item **"CommandTabFree-Sparkle-EdDSA"** + GitHub Actions secret `SPARKLE_ED_PRIVATE_KEY` (env `production`); keychain account `commandtabfree`. `SUEnableAutomaticChecks=false` until a real appcast host exists. This fixed the launch-time "updater failed to start" alert.
|
||||
- **Public release v100.0.1** (pre-release, **unsigned / not notarized**, universal x86_64+arm64). v100.0.0 deleted (had the Sparkle bug).
|
||||
- **Homebrew tap live:** `brew install --cask koftwentytwo/tap/commandtabfree` (`KofTwentyTwo/homebrew-tap` → `Casks/commandtabfree.rb`). Cask strips the quarantine (postflight `xattr`) for the unsigned app.
|
||||
- **Local daily driver installed:** `/Applications/CommandTabFree.app` = **Release** build (no QA menu) signed with the `Local Self-Signed` cert (stable signature → no TCC re-grant loop). Remaining: user grants Accessibility + Screen Recording on first launch.
|
||||
|
||||
### Build / run locally
|
||||
- Ad-hoc (no cert): `xcodebuild -project alt-tab-macos.xcodeproj -scheme Debug -configuration Debug -derivedDataPath DerivedData CODE_SIGN_IDENTITY="-"` → `DerivedData/Build/Products/Debug/CommandTabFree.app`
|
||||
- Stable signature (recommended, fixes the TCC loop): `scripts/codesign/setup_local.sh` (needs keychain/admin approval — user runs it), then `ai/build.sh`; afterwards `rm -f codesign.{conf,key,crt,p12}`.
|
||||
- **TCC permission loop** (ad-hoc rebuilds leave stale grants): `tccutil reset ScreenCapture com.koftwentytwo.commandtabfree && tccutil reset Accessibility com.koftwentytwo.commandtabfree`. The durable fix is the stable cert above.
|
||||
### Build recipes (verified this session)
|
||||
- **Local (stable, no QA menu):** `xcodebuild -project alt-tab-macos.xcodeproj -scheme Release -derivedDataPath DerivedData CURRENT_PROJECT_VERSION=<v> CODE_SIGN_IDENTITY="Local Self-Signed" CODE_SIGN_STYLE=Manual DEVELOPMENT_TEAM="" OTHER_CODE_SIGN_FLAGS="--timestamp=none" CODE_SIGNING_ALLOWED=YES` (needs `scripts/codesign/setup_local.sh` cert first; user runs it — keychain/admin prompt).
|
||||
- **Public artifact (ad-hoc):** same recipe but `CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO`. Zip with `ditto -c -k --sequesterRsrc --keepParent`.
|
||||
- **GOTCHA — do NOT pass `-configuration Release`.** With `-scheme Release` it splits SPM package outputs and breaks clean-build module-map generation (`build/GeneratedModuleMaps/*.modulemap not found`, then "unable to resolve module Cocoa/Sparkle/..."). Use the scheme only (matches `scripts/build_app.sh`). A failed build can corrupt `build/`; recover with `rm -rf build DerivedData` then rebuild.
|
||||
|
||||
## ⏳ NEXT (publish checklist — see `docs/EXECUTION-STATUS.md` §3)
|
||||
Owner-gated, **Apple Developer ID is the long pole** (user struggling): KofTwentyTwo must enroll as an **Organization** under a *separate* Apple ID (their primary is MMLT's Account Holder; account `744245396565` = `kingsrook_root_admin` profile) + D-U-N-S + $99. Then:
|
||||
- Sparkle EdDSA keypair (I generate, owner stores private key as CI secret)
|
||||
- GitHub secrets in a `production` environment; `gh label create sync conflict chokepoint-refresh`; external cron for `upstream_sync.yml`
|
||||
- `DOMAIN`/appcast host → **kof22.com is ready** (see DNS below); replace `fork.invalid` in `local.xcconfig`
|
||||
- **Real icon artwork** (replace placeholder)
|
||||
- Push `depaywall-free` + open PR (runs `guard.yml`, no secrets) → merge → signed/notarized release
|
||||
|
||||
## DNS/mail (DONE this session — infra, not the fork repo)
|
||||
Plan at `/Users/james.maes/Git.Local/kof22/DNS-MAIL-PLAN.md` (outside repo). Both `kof22.com` and `koftwentytwo.com` migrated to benchfinity-style vanity NS (`ns1/ns2.<domain>` glued to `.146`) on the **Synology DNS Server**; `realm.direct` retired for these two. `koftwentytwo.com`: web→`50.122.5.146` (=kof22), MX→`mail.kof22.com` (per-domain mail; each IP runs Postfix/Dovecot), added as MailPlus additional domain on `.146`. Outbound relays via **SocketLabs** (`include:email-od.com`, DKIM CNAME→`dkim._domainkey.email-od.com`). Registrar = AWS acct `744245396565` (`AWS_PROFILE=kingsrook_root_admin`; `--profile` flag breaks the wrapper — use the env var). Inbound mail test was never confirmed (couldn't send from this VPN-blocked machine).
|
||||
|
||||
## Key docs
|
||||
`docs/AUDIT.md` (master audit) · `docs/GRAPHS.md` (mermaid) · `docs/PLAN-maintained-fork.md` (the strategy — thin patch + merge tracking + CI) · `docs/PLAN-republish-free.md` (one-shot excision, superseded) · `docs/EXECUTION-STATUS.md` (publish checklist) · `docs/audit/01–09-*.md` (deep dives).
|
||||
## ⏳ NEXT (owner-gated — `docs/EXECUTION-STATUS.md` §3)
|
||||
- **Apple Developer ID** (long pole): set `CODE_SIGN_IDENTITY` in `config/local.xcconfig`, re-sign Sparkle helpers, notarize → re-release signed/notarized, then drop the cask's quarantine postflight.
|
||||
- **Real DOMAIN/appcast** (kof22.com ready): replace `fork.invalid` in `local.xcconfig`, serve `/appcast.xml`, flip `SUEnableAutomaticChecks` back on.
|
||||
- **Wire CI:** `update_appcast.sh` uses the deprecated `sign_update -s` — switch to `--ed-key-file` (or `--account commandtabfree`) for the new key; create `sync`/`conflict`/`chokepoint-refresh` labels; external cron for `upstream_sync.yml`.
|
||||
- **Real icon artwork** (replace placeholder).
|
||||
|
||||
## Gotchas
|
||||
- Don't merge to master / don't `git revert 9147a4a8` (mixes paywall with a 1869-file reorg).
|
||||
- `aws`: use `AWS_PROFILE=kingsrook_root_admin aws …` (the `--profile` flag fails on the local wrapper); SSO token expires (`aws sso login`).
|
||||
- Bundle id is FROZEN (keychain/UserDefaults suite derives from it).
|
||||
- Bundle id FROZEN (`com.koftwentytwo.commandtabfree`); keychain/UserDefaults suites derive from it.
|
||||
- Don't `git revert 9147a4a8` (mixes paywall with a 1869-file reorg).
|
||||
- Fork version line starts at **v100.0.0** (avoids collision with upstream tags merged into `master`).
|
||||
- `aws`: use `AWS_PROFILE=kingsrook_root_admin aws …` (the `--profile` flag fails on the local wrapper).
|
||||
Reference in new issue
Block a user