fix: cache OAuth across household userIDs; add --side to away#37
Merged
omarshahine merged 2 commits intoApr 19, 2026
Merged
Conversation
… away The token cache was rejecting a valid cached token whenever the currently targeted userID differed from the one stored at auth time. Households share a single OAuth principal (one email) across multiple userIDs, so back-to-back invocations against different sides each forced a fresh password-grant auth and tripped Eight Sleep's 429 rate limit. Tokens are now namespaced strictly by Identity (base URL + client ID + email), which is the authoritative boundary. The cached UserID stays as informational metadata for populating c.UserID when the caller didn't supply one. Also wires --side/--target-user-id into `away on|off` so both household members can target their side symmetrically, matching on/off/temp/status. --both still applies to every household member and now errors cleanly if combined with --side. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…ber test - Extract targetScope() in targeting.go so callers can compose a scope label without TrimPrefix-ing the leading " for " out of targetSuffix(). - Revert the map[bool]string cleverness in away.go to the plain if/else form used elsewhere in the codebase. - Add unit test locking in the requireAuthFields no-clobber guard: an explicit user_id (via flag or config) must survive a successful cache load. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
0xble
added a commit
to 0xble/eightctl
that referenced
this pull request
Apr 20, 2026
Merge upstream/main (steipete#35 side-aware targeting, steipete#36 away-mode fixes and keychain fallback, steipete#37 cache OAuth across household userIDs). Conflict resolution highlights: - tokencache: keep fork's JSON-file fallback and FileBackend-only keyring; drop expectedUserID filter in Load to match upstream household sharing semantic from steipete#37 - eightsleep.go: add doApp wrapper routing to AppURL via doWithBase, keep fork's API drift resilience (fallbackBaseURL, legacyLoginBaseURL, explicit gzip handling), pull in resolveTZ for presence.go - cmd: use resolveAPITimezone (upstream's IANA fallback) instead of fork's time.Local.String() hack - root_test: combine SetOpenKeyringForTest with SetFallbackPathForTest
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
tokencache.Loadwas rejecting a valid cached token whenever the currently-targeted userID differed from the one stored at auth time. Households share one OAuth principal across multiple userIDs, so running e.g.eightctl away onfor one side then the other in separate invocations forced a fresh password-grant auth each time and tripped Eight Sleep's 429 rate limit. Tokens are now namespaced strictly byIdentity(base URL + client ID + email); the cachedUserIDstays as informational metadata used to populatec.UserIDwhen the caller didn't supply one.away on|offnow accepts--side left|right|soloand--target-user-id, matchingon/off/temp/status. This removes the asymmetry where only the config-default side could be toggled without an explicit--user-id.--bothstill applies to every household member and now errors cleanly if combined with--side.Test plan
go test ./...— all green (tokencache + client + cmd)go build ./.../go vet ./...eightctl away on --helpshows new--side/--target-user-idflagseightctl away on --side leftandeightctl away on --side rightback-to-back in separate invocations; verify no 429 and a single network auth in verbose modeeightctl away on --bothand confirm both sides toggle without re-autheightctl away onwith no flags and confirm it still targets the authenticated user's side (unchanged default)🤖 Generated with Claude Code