fix: scope git askpass diff status updates to initiating chat (#22534)

## Problem

When the git askpass flow triggered diff status refreshes, it updated
**every chat** connected to the workspace. This was wasteful and could
cause confusing status updates on unrelated chats.

## Solution

Thread the chat ID through the entire git askpass flow so only the chat
that initiated the git operation gets updated:

1. **`coderd/chatd/chattool/execute.go`** — Sets `CODER_CHAT_ID` env var
on spawned processes (alongside the existing `CODER_CHAT_AGENT`)
2. **`cli/gitaskpass.go`** — Reads `CODER_CHAT_ID` from the environment
and sends it as a `chat_id` query parameter in the `ExternalAuthRequest`
3. **`codersdk/agentsdk/agentsdk.go`** — Adds `ChatID` field to
`ExternalAuthRequest` and encodes it as a query param
4. **`coderd/workspaceagents.go`** — Parses `chat_id` query param and
passes it through to `storeChatGitRef` and
`triggerWorkspaceChatDiffStatusRefresh`
5. **`coderd/chats.go`** — `storeChatGitRef` and
`refreshWorkspaceChatDiffStatuses` now scope updates to just the
initiating chat when a chat ID is provided, falling back to
all-workspace-chats behavior for backwards compatibility (non-chat git
operations)
This commit is contained in:
Kyle Carberry
2026-03-02 22:52:39 -05:00
committed by GitHub
parent 2bdf80d452
commit 56f95a3e6d
7 changed files with 96 additions and 36 deletions
+17 -5
View File
@@ -1835,6 +1835,18 @@ func (api *API) workspaceAgentsExternalAuth(rw http.ResponseWriter, r *http.Requ
Branch: strings.TrimSpace(query.Get("git_branch")),
RemoteOrigin: strings.TrimSpace(query.Get("git_remote_origin")),
}
var chatID uuid.NullUUID
if rawChatID := query.Get("chat_id"); rawChatID != "" {
parsed, err := uuid.Parse(rawChatID)
if err != nil {
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid chat_id.",
Detail: err.Error(),
})
return
}
chatID = uuid.NullUUID{UUID: parsed, Valid: true}
}
// Either match or configID must be provided!
match := query.Get("match")
if match == "" {
@@ -1932,7 +1944,7 @@ func (api *API) workspaceAgentsExternalAuth(rw http.ResponseWriter, r *http.Requ
// context is retained even if the flow requires an out-of-band login.
if gitRef.Branch != "" || gitRef.RemoteOrigin != "" {
//nolint:gocritic // System context required to persist chat git refs.
api.storeChatGitRef(dbauthz.AsSystemRestricted(ctx), workspace.ID, workspace.OwnerID, gitRef)
api.storeChatGitRef(dbauthz.AsSystemRestricted(ctx), workspace.ID, workspace.OwnerID, chatID, gitRef)
}
var previousToken *database.ExternalAuthLink
@@ -1948,7 +1960,7 @@ func (api *API) workspaceAgentsExternalAuth(rw http.ResponseWriter, r *http.Requ
return
}
api.workspaceAgentsExternalAuthListen(ctx, rw, previousToken, externalAuthConfig, workspace, gitRef)
api.workspaceAgentsExternalAuthListen(ctx, rw, previousToken, externalAuthConfig, workspace, chatID, gitRef)
}
// This is the URL that will redirect the user with a state token.
@@ -2006,11 +2018,11 @@ func (api *API) workspaceAgentsExternalAuth(rw http.ResponseWriter, r *http.Requ
})
return
}
api.triggerWorkspaceChatDiffStatusRefresh(workspace, gitRef)
api.triggerWorkspaceChatDiffStatusRefresh(workspace, chatID, gitRef)
httpapi.Write(ctx, rw, http.StatusOK, resp)
}
func (api *API) workspaceAgentsExternalAuthListen(ctx context.Context, rw http.ResponseWriter, previous *database.ExternalAuthLink, externalAuthConfig *externalauth.Config, workspace database.Workspace, gitRef chatGitRef) {
func (api *API) workspaceAgentsExternalAuthListen(ctx context.Context, rw http.ResponseWriter, previous *database.ExternalAuthLink, externalAuthConfig *externalauth.Config, workspace database.Workspace, chatID uuid.NullUUID, gitRef chatGitRef) {
// Since we're ticking frequently and this sign-in operation is rare,
// we are OK with polling to avoid the complexity of pubsub.
ticker, done := api.NewTicker(time.Second)
@@ -2080,7 +2092,7 @@ func (api *API) workspaceAgentsExternalAuthListen(ctx context.Context, rw http.R
})
return
}
api.triggerWorkspaceChatDiffStatusRefresh(workspace, gitRef)
api.triggerWorkspaceChatDiffStatusRefresh(workspace, chatID, gitRef)
httpapi.Write(ctx, rw, http.StatusOK, resp)
return
}