Skip to content

fix(auth): dual-write credentials to keyring AND file#44

Merged
hbrombeer merged 1 commit into
mainfrom
fix/dual-write-credentials
May 8, 2026
Merged

fix(auth): dual-write credentials to keyring AND file#44
hbrombeer merged 1 commit into
mainfrom
fix/dual-write-credentials

Conversation

@hbrombeer
Copy link
Copy Markdown
Member

Summary

The CLI used to delete the JSON credentials file on every successful keyring write. That broke `grounds push` on macOS, because the grounds-push Gradle plugin's `CredentialResolver` only reads the JSON file — `go-keyring` is Go-only.

After this PR, every `Save()` writes to both backends. Read still prefers keyring (canonical), file is the mirror.

Behaviour change

  • macOS / Windows (keyring + file): both kept in sync. Removes the manual `security find-generic-password ... > credentials.json` mirror step.
  • Linux without secret service (file-only): unchanged — keyring write fails silently, file write succeeds, Save returns nil.
  • Both fail: Save returns a combined error (didn't happen before either, but now we surface it explicitly).

Test plan

  • `go test ./internal/auth` green (1 new test `TestSaveDualWritesKeyringAndFile` + existing roundtrip)
  • `go test ./...` all packages green
  • Post-merge end-to-end: `grounds login` on a fresh Mac → `./gradlew groundsPush` works without manual mirror

Memory

Updates the "grounds-push Keychain gap" note — that workaround is no longer needed once this lands and rolls out.

The Save path used to delete the JSON credentials file whenever the
keyring write succeeded. That left macOS users with a working CLI but
a permanently broken `grounds push` flow, because the grounds-push
Gradle plugin's CredentialResolver only reads the JSON file (it doesn't
link go-keyring).

Save now writes to both backends every time and only fails when both
backends fail (so Linux CI hosts without a secret service still work
via the file path alone).

Read still prefers the keyring on platforms that have one — that
remains the canonical store; the file is just a mirror so cross-tool
consumers (Gradle plugin today, anything else tomorrow) don't need to
shell out to `security find-generic-password` to bootstrap.

Closes the gap reported on the multi-plugin-sample push 2026-05-08.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@hbrombeer hbrombeer merged commit c0142ea into main May 8, 2026
5 checks passed
@hbrombeer hbrombeer deleted the fix/dual-write-credentials branch May 8, 2026 07:24
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