unify bridge auth and server env names
This commit is contained in:
parent
235af032b4
commit
cf92887eb1
@ -52,7 +52,7 @@
|
||||
|
||||
bridge 的认证与跨域规则来自:
|
||||
|
||||
- `ACP_AUTH_TOKEN`
|
||||
- `BRIDGE_AUTH_TOKEN`
|
||||
- `ACP_ALLOWED_ORIGINS`
|
||||
|
||||
默认 allowed origins:
|
||||
@ -67,8 +67,8 @@ bridge 的认证与跨域规则来自:
|
||||
- 空 `Origin` 默认允许。
|
||||
- `:*` 表示前缀匹配,例如 `http://localhost:*`。
|
||||
- auth 使用 bearer header。
|
||||
- 如果 `ACP_AUTH_TOKEN` 为空,则接受任意非空 bearer header。
|
||||
- 如果 `ACP_AUTH_TOKEN` 非空,则必须匹配裸 token 或 `Bearer <token>`。
|
||||
- 如果 `BRIDGE_AUTH_TOKEN` 为空,则 bridge auth 默认放行。
|
||||
- 如果 `BRIDGE_AUTH_TOKEN` 非空,则必须匹配裸 token 或 `Bearer <token>`。
|
||||
|
||||
错误行为:
|
||||
|
||||
@ -165,7 +165,7 @@ HTTP 与 WebSocket 统一使用 JSON-RPC 2.0 结构:
|
||||
|
||||
说明:
|
||||
|
||||
- `bridgeOrigin` 读取 `BRIDGE_PUBLIC_BASE_URL`
|
||||
- `bridgeOrigin` 读取 `BRIDGE_SERVER_URL`
|
||||
- 默认值:`https://xworkmate-bridge.svc.plus`
|
||||
|
||||
## 4. Bridge JSON-RPC Methods
|
||||
@ -816,13 +816,13 @@ bridge 在 session 执行期间会通过 `session.update` 推送通知,统一
|
||||
| 变量 | 默认值 | 作用 |
|
||||
| --- | --- | --- |
|
||||
| `ACP_LISTEN_ADDR` | `127.0.0.1:8787` | bridge listen 地址 |
|
||||
| `ACP_AUTH_TOKEN` | 空 | bridge bearer 校验 token |
|
||||
| `BRIDGE_AUTH_TOKEN` | 空 | bridge bearer 校验 token |
|
||||
| `ACP_ALLOWED_ORIGINS` | `https://xworkmate.svc.plus,http://localhost:*,http://127.0.0.1:*` | bridge allowed origins |
|
||||
| `ACP_MULTI_AGENT_ENABLED` | `true` | `acp.capabilities` 中的 `multiAgent` 开关 |
|
||||
| `ACP_MULTI_AGENT_MODEL` | `gpt-4o` | multi-agent 默认模型 |
|
||||
| `BRIDGE_PUBLIC_BASE_URL` | `https://xworkmate-bridge.svc.plus` | bootstrap health 中的 public base URL |
|
||||
| `BRIDGE_SERVER_URL` | `https://xworkmate-bridge.svc.plus` | bootstrap health 与外部调用统一使用的 bridge base URL |
|
||||
| `INTERNAL_SERVICE_TOKEN` | 空 | upstream provider / gateway 优先使用的内部服务 token |
|
||||
| `BRIDGE_AUTH_TOKEN` | 空 | `INTERNAL_SERVICE_TOKEN` 的 fallback,用于 upstream forwarding |
|
||||
| `BRIDGE_AUTH_TOKEN` | 空 | bridge 入站 bearer token;当 `INTERNAL_SERVICE_TOKEN` 为空时也作为 upstream forwarding token |
|
||||
| `IMAGE` | 空 | `/api/ping` 版本信息来源 |
|
||||
|
||||
### 9.2 Gemini adapter
|
||||
|
||||
@ -159,10 +159,10 @@ single-agent 主链路优先走 bridge 内建 provider catalog。`runSingleAgent
|
||||
|
||||
### 4.1 Auth
|
||||
|
||||
bridge 主入口使用 `ACP_AUTH_TOKEN` 驱动的 bearer auth:
|
||||
bridge 主入口使用 `BRIDGE_AUTH_TOKEN` 驱动的 bearer auth:
|
||||
|
||||
- 如果配置了 token,则必须完全匹配该 token 或 `Bearer <token>`
|
||||
- 如果未配置 token,则只要求存在非空 bearer header
|
||||
- 如果未配置 token,则默认放行
|
||||
|
||||
Gemini adapter 的 auth 更宽松:
|
||||
|
||||
|
||||
@ -60,7 +60,7 @@ APP-facing bridge 主控面。负责 HTTP / WebSocket 路由、JSON-RPC method d
|
||||
- `func (s *Server) HandleBridgeBootstrapHealth(w http.ResponseWriter, r *http.Request)`
|
||||
- 参数:标准 HTTP writer/request。
|
||||
- 返回:无显式返回;输出 bridge health JSON。
|
||||
- 副作用:读取 `BRIDGE_PUBLIC_BASE_URL`。
|
||||
- 副作用:读取 `BRIDGE_SERVER_URL`。
|
||||
- 场景:bootstrap 自检或部署健康检查。
|
||||
|
||||
- `func RunStdio(input io.Reader, output io.Writer)`
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
# Example configuration for xworkmate-bridge public ingress and provider sync.
|
||||
# The bridge itself validates inbound requests with:
|
||||
# Authorization: Bearer ${ACP_AUTH_TOKEN}
|
||||
# Authorization: Bearer ${BRIDGE_AUTH_TOKEN}
|
||||
# Each external provider can also carry its own outbound Authorization header.
|
||||
|
||||
bridge:
|
||||
listenAddr: 127.0.0.1:8787
|
||||
authToken: ${ACP_AUTH_TOKEN}
|
||||
authToken: ${BRIDGE_AUTH_TOKEN}
|
||||
allowedOrigins:
|
||||
- https://xworkmate.svc.plus
|
||||
- http://localhost:*
|
||||
@ -37,6 +37,6 @@ providers:
|
||||
enabled: true
|
||||
|
||||
notes:
|
||||
- The bridge reads its own auth token from ACP_AUTH_TOKEN.
|
||||
- The bridge reads its own auth token from BRIDGE_AUTH_TOKEN.
|
||||
- The provider catalog is normally synced through xworkmate.providers.sync.
|
||||
- session.message should resend routing on follow-up turns for codex and opencode.
|
||||
|
||||
@ -22,7 +22,7 @@ func (s *Server) HandleBridgeBootstrapHealth(w http.ResponseWriter, r *http.Requ
|
||||
}
|
||||
|
||||
func bridgePublicBaseURL() string {
|
||||
value := strings.TrimSpace(shared.EnvOrDefault("BRIDGE_PUBLIC_BASE_URL", "https://xworkmate-bridge.svc.plus"))
|
||||
value := strings.TrimSpace(shared.EnvOrDefault("BRIDGE_SERVER_URL", "https://xworkmate-bridge.svc.plus"))
|
||||
if value == "" {
|
||||
return "https://xworkmate-bridge.svc.plus"
|
||||
}
|
||||
|
||||
@ -96,7 +96,7 @@ func NewServer() *Server {
|
||||
gateway: gatewayruntime.NewManager(),
|
||||
providerCatalog: providerCatalog,
|
||||
providerOrder: providerOrder,
|
||||
authService: service.NewStaticTokenAuthService(strings.TrimSpace(shared.EnvOrDefault("ACP_AUTH_TOKEN", ""))),
|
||||
authService: service.NewStaticTokenAuthService(strings.TrimSpace(shared.EnvOrDefault("BRIDGE_AUTH_TOKEN", ""))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,7 +300,14 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (s *Server) authorized(r *http.Request) bool {
|
||||
if s == nil || s.authService == nil {
|
||||
if s == nil {
|
||||
return false
|
||||
}
|
||||
expected := strings.TrimSpace(shared.EnvOrDefault("BRIDGE_AUTH_TOKEN", ""))
|
||||
if expected == "" {
|
||||
return true
|
||||
}
|
||||
if s.authService == nil {
|
||||
return false
|
||||
}
|
||||
return s.authService.ValidateAuthorizationHeader(r.Header.Get("Authorization"))
|
||||
|
||||
@ -110,7 +110,26 @@ func TestHandleRPCAllowsPreflightForConfiguredOrigin(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleRPCRequiresBearerAuthorization(t *testing.T) {
|
||||
func TestHandleRPCAllowsRequestsWhenBridgeAuthTokenUnset(t *testing.T) {
|
||||
server := NewServer()
|
||||
recorder := httptest.NewRecorder()
|
||||
request := httptest.NewRequest(
|
||||
http.MethodPost,
|
||||
"http://127.0.0.1/acp/rpc",
|
||||
strings.NewReader(`{"jsonrpc":"2.0","id":1,"method":"acp.capabilities"}`),
|
||||
)
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
server.HandleRPC(recorder, request)
|
||||
|
||||
if recorder.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200 when BRIDGE_AUTH_TOKEN is unset, got %d", recorder.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleRPCRequiresBearerAuthorizationWhenBridgeAuthTokenConfigured(t *testing.T) {
|
||||
t.Setenv("BRIDGE_AUTH_TOKEN", "bridge-test-token")
|
||||
|
||||
server := NewServer()
|
||||
recorder := httptest.NewRecorder()
|
||||
request := httptest.NewRequest(
|
||||
@ -195,6 +214,14 @@ func TestHandleRPCCapabilitiesStillReturnsJSONResult(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthorizedAllowsRequestsWhenBridgeAuthTokenUnset(t *testing.T) {
|
||||
server := NewServer()
|
||||
request := httptest.NewRequest(http.MethodGet, "http://127.0.0.1/acp", nil)
|
||||
if !server.authorized(request) {
|
||||
t.Fatal("expected requests to be authorized when BRIDGE_AUTH_TOKEN is unset")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleRPCCapabilitiesReturnsCanonicalProviderContract(t *testing.T) {
|
||||
server := NewServer()
|
||||
recorder := httptest.NewRecorder()
|
||||
@ -338,6 +365,7 @@ func mustStringList(t *testing.T, value any) []string {
|
||||
|
||||
func TestHandleWebSocketRequiresBearerAuthorization(t *testing.T) {
|
||||
t.Setenv("ACP_ALLOWED_ORIGINS", "https://xworkmate.svc.plus")
|
||||
t.Setenv("BRIDGE_AUTH_TOKEN", "bridge-test-token")
|
||||
|
||||
server := NewServer()
|
||||
recorder := httptest.NewRecorder()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user