Skip to content

feat(session): store session in macOS Keychain by default#248

Merged
ernado merged 1 commit into
gotd:mainfrom
yagop:feat/keychain-session
Jun 27, 2026
Merged

feat(session): store session in macOS Keychain by default#248
ernado merged 1 commit into
gotd:mainfrom
yagop:feat/keychain-session

Conversation

@yagop

@yagop yagop commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

What

On macOS, the Telegram session is now stored in the login Keychain by default instead of a plaintext file in the config dir. Other platforms keep using the file backend, unchanged.

Why

The session string is the full auth credential. Keeping it as a 0600 file in ~/Library/Application Support/gotd/ is weaker than the OS keystore. The Keychain is the native macOS secret store and needs no new dependency.

How

  • New sessionStore abstraction (cmd/tg/session_store.go) — a single seam for read / exists / delete — with two backends:
    • file (session.FileStorage, existing behaviour) — used off macOS and when disabled.
    • macOS Keychain (cmd/tg/session_keychain_darwin.go) via the security CLI. No cgo, so the static cross-compiled release binary is unaffected.
  • The three call sites that touched session files now go through the store: client wiring (app.go), logout (delete), accounts (existence).
  • Default on on macOS; opt out with keychain: false in the config (e.g. headless macOS). Non-darwin always uses a file.
  • Automatic migration: an existing file session is imported into the Keychain on first use and the file removed; logout clears both.
  • Keychain item: service gotd.session, account <label>.<kind>.<seed> — mirrors the on-disk filename scheme, so multi-account and user/bot never collide.

Tests

  • session_store_test.go — default-on logic, account naming, file round-trip (cross-platform).
  • session_keychain_darwin_test.go — argv builders, exit-44→ErrNotFound mapping, and a real migration round-trip against the login Keychain (darwin-only; CI is Linux so it never runs there).
  • go test -race ./..., go vet, and gofmt all clean.

🤖 Generated with Claude Code

Add a sessionStore abstraction so session read/exists/delete go through a
single seam, with two backends: a file (existing behaviour, used off macOS
and when keychain is disabled) and the macOS login Keychain via the
`security` CLI (no cgo, keeps the static binary).

Keychain is the default on macOS; set `keychain: false` to opt out. An
existing file session is migrated into the Keychain on first use and the
file is removed; logout clears both.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ernado ernado merged commit c276ae0 into gotd:main Jun 27, 2026
4 checks passed
@yagop yagop deleted the feat/keychain-session branch June 27, 2026 15:22
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.

2 participants