Skip to content

Defer Keychain access, use agy CLI only, and sign releases with a stable certificate - #1

Merged
aryan1306 merged 2 commits into
mainfrom
feat/deferred-keychain-agy-cli
Sep 25, 2026
Merged

aryan1306 merged 2 commits into
mainfrom
feat/deferred-keychain-agy-cli

Conversation

@aryan1306

Copy link
Copy Markdown
Owner

Why

Launching LLMits showed several Keychain access prompts, and they came back after every update.

  • start() read the Keychain for every provider, including ones that were never connected, with one Keychain item per provider.
  • Reading agy's gemini/antigravity Keychain item was on by default. That item belongs to agy, so macOS always prompts before LLMits can read it.
  • Releases were ad-hoc signed, so every update had a new code identity and lost "Always Allow".

What changes for users

  • No prompts on launch. The app trusts the saved connection list. Credentials are read only when a connected provider refreshes, and once per session after that. A fresh install never prompts until the user clicks Connect.
  • Antigravity uses only the agy CLI. Google OAuth is removed. Connect checks the agy login by running agy -p /usage. LLMits never reads agy's credentials, so connecting Antigravity never prompts. Existing Google sign-ins switch over to the CLI.
  • One Keychain item. Claude and Codex credentials are stored together, so there is at most one prompt. Old per-provider items are copied over the first time they're needed, and removed when that provider is disconnected.
  • A denied prompt isn't repeated. The 5-minute polling skips a provider after a Keychain error, as it already did for agy errors. A manual refresh or reconnect tries again.
  • Updates keep Keychain approval. Releases are signed with a stable self-signed certificate. Every build now shares the same code identity (identifier "com.llmits.app" and certificate root = H"ad1c6cab…"), so Keychain approval carries over to new versions. Gatekeeper's first-launch warning is unchanged; only a Developer ID fixes that.

Existing users will see one last round of prompts on the first signed release, because their items were saved by ad-hoc builds.

Release setup

  • build-dmg.sh signs with a PKCS#12 identity from CODESIGN_P12_PATH or CODESIGN_P12_BASE64 plus CODESIGN_P12_PASSWORD. It uses a temporary keychain and restores the user's keychain search list afterwards. Without these variables it signs ad-hoc and prints a warning.
  • Tag releases fail if the CODESIGN_P12_BASE64 or CODESIGN_P12_PASSWORD secret is missing. Both are already set on the repository.

Verification

  • swift build
  • swift test: 56 tests pass, 1 skipped (the live update test). The new CredentialAccessTests covers: no Keychain reads on a fresh launch, reads limited to connected providers, disconnecting a provider whose credential is missing, no retry after a denied prompt until a manual refresh, connecting Antigravity through the CLI (success and failure), and carrying over an old Google sign-in.
  • Signed ./scripts/build-dmg.sh locally with both the path and the base64 inputs. Rebuilt with a source change, and the second build met the first build's code identity requirement. Confirmed the keychain search list was restored.
  • git diff --check
  • Not yet checked by hand: watching the real app's Keychain prompts during launch, connect and update.

…cess

Remove the Antigravity Google OAuth flow and the direct read of agy's
Keychain item; connecting now verifies the agy login by running its
read-only /usage report.

Launch no longer probes the Keychain: the saved connection list is
trusted and credentials are read only when a connected provider
refreshes. Claude and Codex credentials share one cached Keychain item
(migrated from the per-provider items), and a denied Keychain prompt is
not retried by polling until a manual refresh.
Ad-hoc signatures change the app's designated requirement on every
build, so macOS re-prompts for Keychain access after each update.
build-dmg.sh now signs with a PKCS#12 identity from CODESIGN_P12_PATH or
CODESIGN_P12_BASE64 via a temporary keychain, and tagged releases fail
without the signing secrets.
@gitguardian

gitguardian Bot commented Sep 25, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 2 secrets following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secrets in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
37595592 Triggered Generic Password c4e19a4 .github/workflows/release.yml View secret
37595592 Triggered Generic Password c4e19a4 scripts/build-dmg.sh View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secrets safely. Learn here the best practices.
  3. Revoke and rotate these secrets.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@aryan1306
aryan1306 merged commit ba21747 into main Sep 25, 2026
2 checks passed
@aryan1306
aryan1306 deleted the feat/deferred-keychain-agy-cli branch September 25, 2026 07:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant