feat: byok observability api (#24207)

## Summary
Exposes `credential_kind` and `credential_hint` on AI Bridge session
threads, making credential metadata visible in the session detail API.
   
Each thread in the `/api/v2/aibridge/sessions/{session_id}` response now
includes:
- `credential_kind`: `centralized` or `byok`
- `credential_hint`: masked credential (e.g. `sk-a...pgAA`)
Values are taken from the thread's root interception.
## Changes

- `codersdk/aibridge.go`: Added `CredentialKind` and `CredentialHint`
fields to `AIBridgeThread`
- `coderd/database/db2sdk/db2sdk.go`: Populated from root interception
in `buildAIBridgeThread`
  - `SessionTimeline.stories.tsx`: Added fields to mock thread data
This commit is contained in:
Yevhenii Shcherbina
2026-04-09 11:41:17 -04:00
committed by GitHub
parent 65bf7c3b18
commit 8237822441
8 changed files with 30 additions and 0 deletions
+6
View File
@@ -13239,6 +13239,12 @@ const docTemplate = `{
"$ref": "#/definitions/codersdk.AIBridgeAgenticAction"
}
},
"credential_hint": {
"type": "string"
},
"credential_kind": {
"type": "string"
},
"ended_at": {
"type": "string",
"format": "date-time"
+6
View File
@@ -11809,6 +11809,12 @@
"$ref": "#/definitions/codersdk.AIBridgeAgenticAction"
}
},
"credential_hint": {
"type": "string"
},
"credential_kind": {
"type": "string"
},
"ended_at": {
"type": "string",
"format": "date-time"
+2
View File
@@ -1240,6 +1240,8 @@ func buildAIBridgeThread(
if rootIntc != nil {
thread.Model = rootIntc.Model
thread.Provider = rootIntc.Provider
thread.CredentialKind = string(rootIntc.CredentialKind)
thread.CredentialHint = rootIntc.CredentialHint
// Get first user prompt from root interception.
// A thread can only have one prompt, by definition, since we currently
// only store the last prompt observed in an interception.
+2
View File
@@ -127,6 +127,8 @@ type AIBridgeThread struct {
Prompt *string `json:"prompt,omitempty"`
Model string `json:"model"`
Provider string `json:"provider"`
CredentialKind string `json:"credential_kind"`
CredentialHint string `json:"credential_hint"`
StartedAt time.Time `json:"started_at" format:"date-time"`
EndedAt *time.Time `json:"ended_at,omitempty" format:"date-time"`
TokenUsage AIBridgeSessionThreadsTokenUsage `json:"token_usage"`
+2
View File
@@ -334,6 +334,8 @@ curl -X GET http://coder-server:8080/api/v2/aibridge/sessions/{session_id} \
]
}
],
"credential_hint": "string",
"credential_kind": "string",
"ended_at": "2019-08-24T14:15:22Z",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"model": "string",
+6
View File
@@ -884,6 +884,8 @@
]
}
],
"credential_hint": "string",
"credential_kind": "string",
"ended_at": "2019-08-24T14:15:22Z",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"model": "string",
@@ -1019,6 +1021,8 @@
]
}
],
"credential_hint": "string",
"credential_kind": "string",
"ended_at": "2019-08-24T14:15:22Z",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"model": "string",
@@ -1043,6 +1047,8 @@
| Name | Type | Required | Restrictions | Description |
|-------------------|----------------------------------------------------------------------------------------|----------|--------------|-------------|
| `agentic_actions` | array of [codersdk.AIBridgeAgenticAction](#codersdkaibridgeagenticaction) | false | | |
| `credential_hint` | string | false | | |
| `credential_kind` | string | false | | |
| `ended_at` | string | false | | |
| `id` | string | false | | |
| `model` | string | false | | |
+2
View File
@@ -193,6 +193,8 @@ export interface AIBridgeThread {
readonly prompt?: string;
readonly model: string;
readonly provider: string;
readonly credential_kind: string;
readonly credential_hint: string;
readonly started_at: string;
readonly ended_at?: string;
readonly token_usage: AIBridgeSessionThreadsTokenUsage;
@@ -10,6 +10,8 @@ const mockThread: AIBridgeThread = {
"Can you check what files are in the project and summarize the structure?",
model: "claude-opus-4-6",
provider: "anthropic",
credential_kind: "centralized",
credential_hint: "sk-a...efgh",
started_at: "2026-03-09T09:28:15.000Z",
ended_at: "2026-03-09T09:28:47.000Z",
token_usage: {
@@ -58,6 +60,8 @@ const mockThreadLong: AIBridgeThread = {
"Please refactor the authentication module so that it uses the new token-based flow we discussed. Make sure to update all the related tests and add inline comments explaining the security rationale for each change.",
model: "claude-opus-4-6",
provider: "anthropic",
credential_kind: "centralized",
credential_hint: "sk-a...efgh",
started_at: "2026-03-09T10:00:00.000Z",
ended_at: "2026-03-09T10:05:30.000Z",
token_usage: {