Skip to content

docs: credential storage spike (headless Linux, containers, WSL, Windows) - #6

Open
RogerCecilpot wants to merge 1 commit into
feat/259-update-notifierfrom
spike/261-credential-storage
Open

RogerCecilpot wants to merge 1 commit into
feat/259-update-notifierfrom
spike/261-credential-storage

Conversation

@RogerCecilpot

@RogerCecilpot RogerCecilpot commented Oct 25, 2026 •

Copy link
Copy Markdown

Closes devlyft/devlyft#261.

Findings: docs/spikes/2026-10-credential-storage.md

Summary

  • Size is fine. API tokens are 47 B. A full OAuth credential blob is about 0.8 KB, and 1.3 KB with a 254-char email. Windows' limit is 2560 bytes of raw blob: go-keyring stores the string's bytes, not UTF-16, so the limit is not halved. macOS caps at about 2.9 KB, and the secret goes to security -i over stdin, not argv.
  • Availability is the problem. On WSL2, headless sessions and containers there is no Secret Service, and go-keyring fails within milliseconds. Errors are dbus.Error, *exec.Error (dbus-launch missing) or a plain errorString, so there is no sentinel to match. With dbus-x11 installed, godbus autolaunches a stray dbus-daemon. With gnome-keyring unlocked, every size up to 64 KB works.
  • No timeout. go-keyring waits forever on an unlock prompt. gh wraps every call in a 60 s timeout for this reason. The hang didn't reproduce headless, because those cases fail before reaching a prompt.

Recommendation

Add an internal/auth/credstore wrapper:

  • a timeout on every keyring call (3 s off a TTY, 60 s at one)
  • any keyring error other than not-found means "unavailable", which falls back to a 0600 file with a one-time warning
  • skip the keyring entirely when DEVLYFT_API_TOKEN, CI or a container marker is present, or when there is no session bus
  • record which store holds each account
  • keep only the refresh token and metadata in the keyring, and the access token in memory

These feed into devlyft/devlyft#245 (credential store) and devlyft/devlyft#263 (browser login).

Also in this PR

  • hack/keyring-probe: a throwaway probe.
  • .github/workflows/spike-keyring.yml: manual dispatch only, hosted runners, no secrets. It confirms the macOS and Windows numbers.
  • Delete both once devlyft/devlyft#245 lands.

🤖 Generated with Claude Code

@RogerCecilpot
RogerCecilpot force-pushed the spike/261-credential-storage branch from aa3af18 to 234c8f2 Compare October 25, 2026 12:56
@RogerCecilpot
RogerCecilpot changed the base branch from feat/235-scaffold to feat/259-update-notifier October 25, 2026 12:57
@RogerCecilpot
RogerCecilpot force-pushed the feat/259-update-notifier branch from 479e755 to 4bfb39f Compare October 25, 2026 13:00
@RogerCecilpot
RogerCecilpot force-pushed the spike/261-credential-storage branch from 234c8f2 to 82ef0d4 Compare October 25, 2026 13:00
Probe go-keyring on WSL2, headless sessions and containers, and read the
Windows and macOS backends to check size limits. Stored credentials fit
everywhere (worst case ~1.3 KB vs Windows' 2560-byte raw blob limit);
the real issue is that headless Linux, WSL and CI have no Secret Service,
and go-keyring has no timeout. Recommends a credstore wrapper with a
timeout and file fallback, skip rules, and keeping only the refresh token
in the keyring.

Adds a throwaway probe (hack/keyring-probe) and a manual-dispatch
workflow to confirm the macOS and Windows numbers on hosted runners.

Refs devlyft/devlyft#261

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@RogerCecilpot
RogerCecilpot force-pushed the feat/259-update-notifier branch from 4bfb39f to 60cf131 Compare October 25, 2026 13:32
@RogerCecilpot
RogerCecilpot force-pushed the spike/261-credential-storage branch from 82ef0d4 to d0d5548 Compare October 25, 2026 13:32
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