win 21325afb33
Some checks failed
CI / test (push) Failing after 10s
CI / frontend (push) Failing after 8s
CI / golangci-lint (push) Failing after 5s
Security Scan / backend-security (push) Failing after 5s
Security Scan / frontend-security (push) Failing after 4s
feat(windsurf): 补全ops日志记录与endpoint派生,对齐其他平台
- windsurf_gateway_service: 添加上游延迟/TTFT/错误上下文记录
- endpoint: DeriveUpstreamEndpoint 添加 PlatformWindsurf 分支
- ops_error_logger: guessPlatformFromPath 添加 /windsurf/ 识别
2026-04-23 20:46:27 +08:00

54 lines
1.6 KiB
Go

// JWT decoding helpers.
// Portions derived from windsurf-tools (MIT 2025 shaoyu521). See ./LICENSE.
package windsurf
import (
"crypto/rand"
"encoding/base64"
"encoding/json"
"fmt"
"strings"
)
// readRandom abstracts crypto/rand.Read for testability.
func readRandom(b []byte) (int, error) { return rand.Read(b) }
// JWTClaims holds the fields we care about from the Windsurf session JWT.
type JWTClaims struct {
SessionID string `json:"session_id,omitempty"`
UserID string `json:"user_id,omitempty"`
TeamID string `json:"team_id,omitempty"`
AuthUID string `json:"auth_uid,omitempty"`
Exp int64 `json:"exp,omitempty"`
}
// StripDevinPrefix returns the raw JWT (without the "devin-session-token$" prefix).
func StripDevinPrefix(token string) string {
if i := strings.Index(token, "$"); i >= 0 && strings.HasPrefix(token, "devin-session-token$") {
return token[i+1:]
}
return token
}
// DecodeJWTClaims parses the payload portion of a JWT (after stripping the
// optional "devin-session-token$" prefix). It does NOT verify the signature.
func DecodeJWTClaims(token string) (*JWTClaims, error) {
jwt := StripDevinPrefix(token)
parts := strings.Split(jwt, ".")
if len(parts) != 3 {
return nil, fmt.Errorf("jwt: expected 3 segments, got %d", len(parts))
}
payload, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
payload, err = base64.URLEncoding.DecodeString(parts[1])
if err != nil {
return nil, fmt.Errorf("jwt payload base64: %w", err)
}
}
var claims JWTClaims
if err := json.Unmarshal(payload, &claims); err != nil {
return nil, fmt.Errorf("jwt payload json: %w", err)
}
return &claims, nil
}