From 988b15f50c40f56c9d539d7777526bc0c41c0783 Mon Sep 17 00:00:00 2001 From: Luke Hagar Date: Mon, 1 Jun 2026 13:53:01 -0500 Subject: [PATCH] Surface SailApps confirmation code during OAuth login Co-authored-by: Cursor --- internal/config/oauth.go | 14 ++++++++++++ internal/config/oauth_test.go | 40 +++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 internal/config/oauth_test.go diff --git a/internal/config/oauth.go b/internal/config/oauth.go index 13f56f58..addbacf7 100644 --- a/internal/config/oauth.go +++ b/internal/config/oauth.go @@ -14,6 +14,7 @@ import ( "fmt" "io" "net/http" + "strings" "time" "github.com/charmbracelet/log" @@ -61,6 +62,16 @@ type AuthResponse struct { TTL int64 `json:"ttl"` } +func confirmationCodeFromID(id string) string { + id = strings.TrimSpace(id) + if len(id) < 8 { + return strings.ToUpper(id) + } + + suffix := id[len(id)-8:] + return strings.ToUpper(suffix[:4] + "-" + suffix[4:]) +} + // OAuthTokenResponse represents the response containing the encrypted token from OAuth flow type OAuthTokenResponse struct { ID string `json:"id"` @@ -415,6 +426,9 @@ func OAuthLogin() (TokenSet, error) { } log.Debug("Auth response received", "id", authResponse.ID, "baseURL", authResponse.BaseURL) + if confirmationCode := confirmationCodeFromID(authResponse.ID); confirmationCode != "" { + fmt.Printf("SailApps confirmation code: %s\n", confirmationCode) + } // Update the base URL for this session if authResponse.BaseURL != "" { diff --git a/internal/config/oauth_test.go b/internal/config/oauth_test.go new file mode 100644 index 00000000..8333e563 --- /dev/null +++ b/internal/config/oauth_test.go @@ -0,0 +1,40 @@ +package config + +import "testing" + +func TestConfirmationCodeFromID(t *testing.T) { + tests := []struct { + name string + id string + want string + }{ + { + name: "uuid uses last eight characters", + id: "12345678-90ab-cdef-1234-567890abcdef", + want: "90AB-CDEF", + }, + { + name: "short id is uppercased", + id: "abc123", + want: "ABC123", + }, + { + name: "whitespace is ignored", + id: " 12345678-90ab-cdef-1234-567890abcdef ", + want: "90AB-CDEF", + }, + { + name: "empty id stays empty", + id: "", + want: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := confirmationCodeFromID(tt.id); got != tt.want { + t.Fatalf("confirmationCodeFromID(%q) = %q, want %q", tt.id, got, tt.want) + } + }) + } +}