Unify bridge sync contract names
This commit is contained in:
parent
412573bdbd
commit
9b0d99c7f0
@ -26,14 +26,14 @@ type xworkmateAccessContext struct {
|
||||
}
|
||||
|
||||
type xworkmateProfilePayload struct {
|
||||
OpenclawURL string `json:"openclawUrl"`
|
||||
OpenclawOrigin string `json:"openclawOrigin"`
|
||||
VaultURL string `json:"vaultUrl"`
|
||||
VaultNamespace string `json:"vaultNamespace"`
|
||||
VaultSecretPath string `json:"vaultSecretPath"`
|
||||
VaultSecretKey string `json:"vaultSecretKey"`
|
||||
SecretLocators []xworkmateSecretLocatorPayload `json:"secretLocators"`
|
||||
ApisixURL string `json:"apisixUrl"`
|
||||
BridgeServerURL string `json:"BRIDGE_SERVER_URL"`
|
||||
BridgeServerOrigin string `json:"bridgeServerOrigin"`
|
||||
VaultURL string `json:"vaultUrl"`
|
||||
VaultNamespace string `json:"vaultNamespace"`
|
||||
VaultSecretPath string `json:"vaultSecretPath"`
|
||||
VaultSecretKey string `json:"vaultSecretKey"`
|
||||
SecretLocators []xworkmateSecretLocatorPayload `json:"secretLocators"`
|
||||
ApisixURL string `json:"apisixUrl"`
|
||||
}
|
||||
|
||||
type xworkmateSecretLocatorPayload struct {
|
||||
@ -46,10 +46,11 @@ type xworkmateSecretLocatorPayload struct {
|
||||
}
|
||||
|
||||
var xworkmateForbiddenTokenFields = map[string]struct{}{
|
||||
"openclawtoken": {},
|
||||
"gatewaytoken": {},
|
||||
"vaulttoken": {},
|
||||
"apisixtoken": {},
|
||||
"bridge_auth_token": {},
|
||||
"bridgeauthtoken": {},
|
||||
"gatewaytoken": {},
|
||||
"vaulttoken": {},
|
||||
"apisixtoken": {},
|
||||
}
|
||||
|
||||
func (h *handler) ensureSharedXWorkmateTenant(ctx context.Context) error {
|
||||
@ -256,16 +257,16 @@ func buildSessionTenantEntries(memberships []store.TenantMembership) []gin.H {
|
||||
|
||||
func buildXWorkmateTokenConfigured(profile *store.XWorkmateProfile) gin.H {
|
||||
result := gin.H{
|
||||
"openclaw": false,
|
||||
"vault": false,
|
||||
"apisix": false,
|
||||
"bridge": false,
|
||||
"vault": false,
|
||||
"apisix": false,
|
||||
}
|
||||
if profile == nil {
|
||||
return result
|
||||
}
|
||||
|
||||
if hasOpenclawXWorkmateSecretLocator(profile) {
|
||||
result["openclaw"] = true
|
||||
if hasBridgeAuthTokenXWorkmateSecretLocator(profile) {
|
||||
result["bridge"] = true
|
||||
}
|
||||
|
||||
return result
|
||||
@ -277,8 +278,8 @@ func buildXWorkmateTokenConfiguredWithVaultStatus(profile *store.XWorkmateProfil
|
||||
return result
|
||||
}
|
||||
|
||||
if configured, ok := vaultStatus[store.XWorkmateSecretLocatorTargetOpenclawGatewayToken]; ok {
|
||||
result["openclaw"] = configured
|
||||
if configured, ok := vaultStatus[store.XWorkmateSecretLocatorTargetBridgeAuthToken]; ok {
|
||||
result["bridge"] = configured
|
||||
}
|
||||
if configured, ok := vaultStatus[store.XWorkmateSecretLocatorTargetVaultRootToken]; ok {
|
||||
result["vault"] = configured
|
||||
@ -290,7 +291,7 @@ func buildXWorkmateTokenConfiguredWithVaultStatus(profile *store.XWorkmateProfil
|
||||
return result
|
||||
}
|
||||
|
||||
func hasOpenclawXWorkmateSecretLocator(profile *store.XWorkmateProfile) bool {
|
||||
func hasBridgeAuthTokenXWorkmateSecretLocator(profile *store.XWorkmateProfile) bool {
|
||||
if profile == nil {
|
||||
return false
|
||||
}
|
||||
@ -299,7 +300,7 @@ func hasOpenclawXWorkmateSecretLocator(profile *store.XWorkmateProfile) bool {
|
||||
return true
|
||||
}
|
||||
for _, locator := range profile.SecretLocators {
|
||||
if locator.Target != store.XWorkmateSecretLocatorTargetOpenclawGatewayToken {
|
||||
if locator.Target != store.XWorkmateSecretLocatorTargetBridgeAuthToken {
|
||||
continue
|
||||
}
|
||||
if strings.TrimSpace(locator.SecretPath) != "" && strings.TrimSpace(locator.SecretKey) != "" {
|
||||
@ -367,18 +368,18 @@ func (h *handler) buildSessionUser(ctx context.Context, host string, user *store
|
||||
|
||||
func buildXWorkmateProfileResponse(access *xworkmateAccessContext, profile *store.XWorkmateProfile, tokenConfigured gin.H) gin.H {
|
||||
resolvedProfile := gin.H{
|
||||
"openclawUrl": "",
|
||||
"openclawOrigin": "",
|
||||
"vaultUrl": "",
|
||||
"vaultNamespace": "",
|
||||
"vaultSecretPath": "",
|
||||
"vaultSecretKey": "",
|
||||
"secretLocators": []gin.H{},
|
||||
"apisixUrl": "",
|
||||
"BRIDGE_SERVER_URL": "",
|
||||
"bridgeServerOrigin": "",
|
||||
"vaultUrl": "",
|
||||
"vaultNamespace": "",
|
||||
"vaultSecretPath": "",
|
||||
"vaultSecretKey": "",
|
||||
"secretLocators": []gin.H{},
|
||||
"apisixUrl": "",
|
||||
}
|
||||
if profile != nil {
|
||||
resolvedProfile["openclawUrl"] = profile.OpenclawURL
|
||||
resolvedProfile["openclawOrigin"] = profile.OpenclawOrigin
|
||||
resolvedProfile["BRIDGE_SERVER_URL"] = profile.BridgeServerURL
|
||||
resolvedProfile["bridgeServerOrigin"] = profile.BridgeServerOrigin
|
||||
resolvedProfile["vaultUrl"] = profile.VaultURL
|
||||
resolvedProfile["vaultNamespace"] = profile.VaultNamespace
|
||||
resolvedProfile["vaultSecretPath"] = profile.VaultSecretPath
|
||||
@ -546,8 +547,8 @@ func statusByTargetFromMetadata(profile *store.XWorkmateProfile, target string)
|
||||
if profile == nil {
|
||||
return false
|
||||
}
|
||||
if target == store.XWorkmateSecretLocatorTargetOpenclawGatewayToken {
|
||||
return hasOpenclawXWorkmateSecretLocator(profile)
|
||||
if target == store.XWorkmateSecretLocatorTargetBridgeAuthToken {
|
||||
return hasBridgeAuthTokenXWorkmateSecretLocator(profile)
|
||||
}
|
||||
for _, locator := range profile.SecretLocators {
|
||||
if locator.Target == strings.ToLower(strings.TrimSpace(target)) &&
|
||||
@ -677,17 +678,17 @@ func (h *handler) updateXWorkmateProfile(c *gin.Context) {
|
||||
profileUserID := resolvedXWorkmateProfileUserID(access, user)
|
||||
|
||||
profile := &store.XWorkmateProfile{
|
||||
TenantID: access.Tenant.ID,
|
||||
UserID: profileUserID,
|
||||
Scope: access.ProfileScope,
|
||||
OpenclawURL: payload.OpenclawURL,
|
||||
OpenclawOrigin: payload.OpenclawOrigin,
|
||||
VaultURL: payload.VaultURL,
|
||||
VaultNamespace: payload.VaultNamespace,
|
||||
VaultSecretPath: payload.VaultSecretPath,
|
||||
VaultSecretKey: payload.VaultSecretKey,
|
||||
SecretLocators: buildStoreXWorkmateSecretLocators(payload.SecretLocators),
|
||||
ApisixURL: payload.ApisixURL,
|
||||
TenantID: access.Tenant.ID,
|
||||
UserID: profileUserID,
|
||||
Scope: access.ProfileScope,
|
||||
BridgeServerURL: payload.BridgeServerURL,
|
||||
BridgeServerOrigin: payload.BridgeServerOrigin,
|
||||
VaultURL: payload.VaultURL,
|
||||
VaultNamespace: payload.VaultNamespace,
|
||||
VaultSecretPath: payload.VaultSecretPath,
|
||||
VaultSecretKey: payload.VaultSecretKey,
|
||||
SecretLocators: buildStoreXWorkmateSecretLocators(payload.SecretLocators),
|
||||
ApisixURL: payload.ApisixURL,
|
||||
}
|
||||
if err := h.store.UpsertXWorkmateProfile(c.Request.Context(), profile); err != nil {
|
||||
respondError(c, http.StatusInternalServerError, "xworkmate_profile_write_failed", "failed to save xworkmate profile")
|
||||
|
||||
@ -50,13 +50,13 @@ type bridgeBootstrapIssueResponse struct {
|
||||
}
|
||||
|
||||
type bridgeBootstrapConsumeResponse struct {
|
||||
TicketID string `json:"ticketId"`
|
||||
TargetBridge string `json:"targetBridge"`
|
||||
OpenclawURL string `json:"openclawUrl"`
|
||||
AuthMode string `json:"authMode"`
|
||||
ExchangeToken string `json:"exchangeToken"`
|
||||
ExpiresAt string `json:"expiresAt"`
|
||||
Scopes []string `json:"scopes"`
|
||||
TicketID string `json:"ticketId"`
|
||||
TargetBridge string `json:"targetBridge"`
|
||||
BridgeServerURL string `json:"BRIDGE_SERVER_URL"`
|
||||
AuthMode string `json:"authMode"`
|
||||
BridgeAuthToken string `json:"BRIDGE_AUTH_TOKEN"`
|
||||
ExpiresAt string `json:"expiresAt"`
|
||||
Scopes []string `json:"scopes"`
|
||||
}
|
||||
|
||||
func sanitizeBridgeTarget(raw string) string {
|
||||
@ -288,7 +288,7 @@ func (h *handler) internalConsumeXWorkmateBridgeBootstrapTicket(c *gin.Context)
|
||||
respondError(c, http.StatusNotFound, "xworkmate_profile_not_found", "xworkmate profile not found")
|
||||
return
|
||||
}
|
||||
locator, ok := findStoredXWorkmateSecretLocator(profile, store.XWorkmateSecretLocatorTargetOpenclawGatewayToken)
|
||||
locator, ok := findStoredXWorkmateSecretLocator(profile, store.XWorkmateSecretLocatorTargetBridgeAuthToken)
|
||||
if !ok {
|
||||
respondError(c, http.StatusConflict, "gateway_token_not_configured", "gateway token is not configured")
|
||||
return
|
||||
@ -298,8 +298,8 @@ func (h *handler) internalConsumeXWorkmateBridgeBootstrapTicket(c *gin.Context)
|
||||
respondError(c, http.StatusConflict, "gateway_token_unavailable", "gateway token is unavailable")
|
||||
return
|
||||
}
|
||||
openclawURL := strings.TrimSpace(profile.OpenclawURL)
|
||||
if openclawURL == "" {
|
||||
bridgeServerURL := strings.TrimSpace(profile.BridgeServerURL)
|
||||
if bridgeServerURL == "" {
|
||||
respondError(c, http.StatusConflict, "gateway_endpoint_not_configured", "gateway endpoint is not configured")
|
||||
return
|
||||
}
|
||||
@ -308,12 +308,12 @@ func (h *handler) internalConsumeXWorkmateBridgeBootstrapTicket(c *gin.Context)
|
||||
h.updateBridgeBootstrapTicket(ticket)
|
||||
|
||||
c.JSON(http.StatusOK, bridgeBootstrapConsumeResponse{
|
||||
TicketID: ticket.TicketID,
|
||||
TargetBridge: ticket.TargetBridge,
|
||||
OpenclawURL: openclawURL,
|
||||
AuthMode: "shared-token",
|
||||
ExchangeToken: gatewayToken,
|
||||
ExpiresAt: ticket.ExpiresAt.Format(time.RFC3339),
|
||||
Scopes: append([]string(nil), ticket.Scopes...),
|
||||
TicketID: ticket.TicketID,
|
||||
TargetBridge: ticket.TargetBridge,
|
||||
BridgeServerURL: bridgeServerURL,
|
||||
AuthMode: "shared-token",
|
||||
BridgeAuthToken: gatewayToken,
|
||||
ExpiresAt: ticket.ExpiresAt.Format(time.RFC3339),
|
||||
Scopes: append([]string(nil), ticket.Scopes...),
|
||||
})
|
||||
}
|
||||
|
||||
@ -83,11 +83,11 @@ func TestBuildXWorkmateTokenConfiguredUsesSecretLocators(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
profile *store.XWorkmateProfile
|
||||
openclaw bool
|
||||
vault bool
|
||||
apisix bool
|
||||
name string
|
||||
profile *store.XWorkmateProfile
|
||||
bridge bool
|
||||
vault bool
|
||||
apisix bool
|
||||
}{
|
||||
{
|
||||
name: "missing secret key stays false",
|
||||
@ -96,26 +96,26 @@ func TestBuildXWorkmateTokenConfiguredUsesSecretLocators(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "legacy path and key mark openclaw configured",
|
||||
name: "legacy path and key mark bridge configured",
|
||||
profile: &store.XWorkmateProfile{
|
||||
VaultSecretPath: "kv/openclaw",
|
||||
VaultSecretKey: "token",
|
||||
},
|
||||
openclaw: true,
|
||||
bridge: true,
|
||||
},
|
||||
{
|
||||
name: "explicit openclaw locator marks openclaw configured",
|
||||
name: "explicit bridge locator marks bridge configured",
|
||||
profile: &store.XWorkmateProfile{
|
||||
SecretLocators: []store.XWorkmateSecretLocator{
|
||||
{
|
||||
Provider: "vault",
|
||||
SecretPath: "kv/openclaw",
|
||||
SecretKey: "token",
|
||||
Target: store.XWorkmateSecretLocatorTargetOpenclawGatewayToken,
|
||||
Target: store.XWorkmateSecretLocatorTargetBridgeAuthToken,
|
||||
},
|
||||
},
|
||||
},
|
||||
openclaw: true,
|
||||
bridge: true,
|
||||
},
|
||||
{
|
||||
name: "other locator stays false",
|
||||
@ -142,8 +142,8 @@ func TestBuildXWorkmateTokenConfiguredUsesSecretLocators(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
result := buildXWorkmateTokenConfigured(tt.profile)
|
||||
if got := result["openclaw"].(bool); got != tt.openclaw {
|
||||
t.Fatalf("expected openclaw=%v, got %v", tt.openclaw, got)
|
||||
if got := result["bridge"].(bool); got != tt.bridge {
|
||||
t.Fatalf("expected bridge=%v, got %v", tt.bridge, got)
|
||||
}
|
||||
if got := result["vault"].(bool); got != tt.vault {
|
||||
t.Fatalf("expected vault=%v, got %v", tt.vault, got)
|
||||
@ -163,14 +163,14 @@ func TestXWorkmateBridgeBootstrapTicketLifecycle(t *testing.T) {
|
||||
|
||||
profileBody, err := json.Marshal(map[string]any{
|
||||
"profile": map[string]any{
|
||||
"openclawUrl": "wss://openclaw.example.com",
|
||||
"BRIDGE_SERVER_URL": "wss://openclaw.example.com",
|
||||
"secretLocators": []map[string]any{
|
||||
{
|
||||
"id": "locator-openclaw",
|
||||
"provider": "vault",
|
||||
"secretPath": "kv/openclaw",
|
||||
"secretKey": "token",
|
||||
"target": store.XWorkmateSecretLocatorTargetOpenclawGatewayToken,
|
||||
"target": store.XWorkmateSecretLocatorTargetBridgeAuthToken,
|
||||
"required": true,
|
||||
},
|
||||
},
|
||||
@ -193,7 +193,7 @@ func TestXWorkmateBridgeBootstrapTicketLifecycle(t *testing.T) {
|
||||
Provider: "vault",
|
||||
SecretPath: "kv/openclaw",
|
||||
SecretKey: "token",
|
||||
Target: store.XWorkmateSecretLocatorTargetOpenclawGatewayToken,
|
||||
Target: store.XWorkmateSecretLocatorTargetBridgeAuthToken,
|
||||
}, "shared-token-value"); err != nil {
|
||||
t.Fatalf("write secret: %v", err)
|
||||
}
|
||||
@ -237,11 +237,11 @@ func TestXWorkmateBridgeBootstrapTicketLifecycle(t *testing.T) {
|
||||
if err := json.Unmarshal(consumeRec.Body.Bytes(), &consumed); err != nil {
|
||||
t.Fatalf("decode bootstrap consume response: %v", err)
|
||||
}
|
||||
if consumed.ExchangeToken != "shared-token-value" {
|
||||
t.Fatalf("expected returned exchange token, got %#v", consumed)
|
||||
if consumed.BridgeAuthToken != "shared-token-value" {
|
||||
t.Fatalf("expected returned bridge auth token, got %#v", consumed)
|
||||
}
|
||||
if consumed.OpenclawURL != "wss://openclaw.example.com" {
|
||||
t.Fatalf("expected returned openclaw url, got %#v", consumed)
|
||||
if consumed.BridgeServerURL != "wss://openclaw.example.com" {
|
||||
t.Fatalf("expected returned bridge server url, got %#v", consumed)
|
||||
}
|
||||
|
||||
replayReq := httptest.NewRequest(http.MethodPost, "/api/internal/xworkmate/bridge/bootstrap/consume", bytes.NewReader([]byte(fmt.Sprintf(`{"ticket":%q,"bridge":%q}`, created.Ticket, created.Bridge))))
|
||||
@ -296,17 +296,17 @@ func TestUpdateAndGetXWorkmateProfileRoundTripsSecretLocators(t *testing.T) {
|
||||
router, _, token := newXWorkmateTestHarness(t)
|
||||
body, err := json.Marshal(map[string]any{
|
||||
"profile": map[string]any{
|
||||
"openclawUrl": "wss://gateway.example.com",
|
||||
"openclawOrigin": "https://gateway.example.com",
|
||||
"vaultUrl": "https://vault.example.com",
|
||||
"vaultNamespace": "team-a",
|
||||
"BRIDGE_SERVER_URL": "wss://gateway.example.com",
|
||||
"bridgeServerOrigin": "https://gateway.example.com",
|
||||
"vaultUrl": "https://vault.example.com",
|
||||
"vaultNamespace": "team-a",
|
||||
"secretLocators": []map[string]any{
|
||||
{
|
||||
"id": "locator-openclaw",
|
||||
"provider": "vault",
|
||||
"secretPath": "kv/openclaw",
|
||||
"secretKey": "token",
|
||||
"target": store.XWorkmateSecretLocatorTargetOpenclawGatewayToken,
|
||||
"target": store.XWorkmateSecretLocatorTargetBridgeAuthToken,
|
||||
"required": true,
|
||||
},
|
||||
{
|
||||
@ -345,11 +345,11 @@ func TestUpdateAndGetXWorkmateProfileRoundTripsSecretLocators(t *testing.T) {
|
||||
|
||||
var resp struct {
|
||||
Profile struct {
|
||||
OpenclawURL string `json:"openclawUrl"`
|
||||
OpenclawOrigin string `json:"openclawOrigin"`
|
||||
VaultURL string `json:"vaultUrl"`
|
||||
VaultNamespace string `json:"vaultNamespace"`
|
||||
SecretLocators []struct {
|
||||
BridgeServerURL string `json:"BRIDGE_SERVER_URL"`
|
||||
BridgeServerOrigin string `json:"bridgeServerOrigin"`
|
||||
VaultURL string `json:"vaultUrl"`
|
||||
VaultNamespace string `json:"vaultNamespace"`
|
||||
SecretLocators []struct {
|
||||
ID string `json:"id"`
|
||||
Provider string `json:"provider"`
|
||||
SecretPath string `json:"secretPath"`
|
||||
@ -362,9 +362,9 @@ func TestUpdateAndGetXWorkmateProfileRoundTripsSecretLocators(t *testing.T) {
|
||||
ApisixURL string `json:"apisixUrl"`
|
||||
} `json:"profile"`
|
||||
TokenConfigured struct {
|
||||
Openclaw bool `json:"openclaw"`
|
||||
Vault bool `json:"vault"`
|
||||
Apisix bool `json:"apisix"`
|
||||
Bridge bool `json:"bridge"`
|
||||
Vault bool `json:"vault"`
|
||||
Apisix bool `json:"apisix"`
|
||||
} `json:"tokenConfigured"`
|
||||
}
|
||||
if err := json.Unmarshal(getRec.Body.Bytes(), &resp); err != nil {
|
||||
@ -380,14 +380,14 @@ func TestUpdateAndGetXWorkmateProfileRoundTripsSecretLocators(t *testing.T) {
|
||||
if resp.Profile.SecretLocators[0].ID != "locator-openclaw" || !resp.Profile.SecretLocators[0].Required {
|
||||
t.Fatalf("expected openclaw locator to round-trip, got %#v", resp.Profile.SecretLocators[0])
|
||||
}
|
||||
if resp.Profile.SecretLocators[0].Target != store.XWorkmateSecretLocatorTargetOpenclawGatewayToken {
|
||||
t.Fatalf("expected openclaw target, got %#v", resp.Profile.SecretLocators[0])
|
||||
if resp.Profile.SecretLocators[0].Target != store.XWorkmateSecretLocatorTargetBridgeAuthToken {
|
||||
t.Fatalf("expected bridge target, got %#v", resp.Profile.SecretLocators[0])
|
||||
}
|
||||
if resp.Profile.SecretLocators[1].Target != store.XWorkmateSecretLocatorTargetAIGatewayAccessToken {
|
||||
t.Fatalf("expected ai gateway target, got %#v", resp.Profile.SecretLocators[1])
|
||||
}
|
||||
if resp.TokenConfigured.Openclaw {
|
||||
t.Fatalf("expected openclaw tokenConfigured=false until a vault-backed secret exists")
|
||||
if resp.TokenConfigured.Bridge {
|
||||
t.Fatalf("expected bridge tokenConfigured=false until a vault-backed secret exists")
|
||||
}
|
||||
if resp.TokenConfigured.Vault {
|
||||
t.Fatalf("expected vault tokenConfigured=false without a vault-backed token locator")
|
||||
@ -403,13 +403,13 @@ func TestUpdateXWorkmateProfileSynthesizesSecretLocatorsFromLegacyFields(t *test
|
||||
router, _, token := newXWorkmateTestHarness(t)
|
||||
body, err := json.Marshal(map[string]any{
|
||||
"profile": map[string]any{
|
||||
"openclawUrl": "wss://gateway.example.com",
|
||||
"openclawOrigin": "https://gateway.example.com",
|
||||
"vaultUrl": "https://vault.example.com",
|
||||
"vaultNamespace": "team-a",
|
||||
"vaultSecretPath": "kv/openclaw",
|
||||
"vaultSecretKey": "token",
|
||||
"apisixUrl": "https://apigw.example.com",
|
||||
"BRIDGE_SERVER_URL": "wss://gateway.example.com",
|
||||
"bridgeServerOrigin": "https://gateway.example.com",
|
||||
"vaultUrl": "https://vault.example.com",
|
||||
"vaultNamespace": "team-a",
|
||||
"vaultSecretPath": "kv/openclaw",
|
||||
"vaultSecretKey": "token",
|
||||
"apisixUrl": "https://apigw.example.com",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
@ -454,8 +454,8 @@ func TestUpdateXWorkmateProfileSynthesizesSecretLocatorsFromLegacyFields(t *test
|
||||
if len(resp.Profile.SecretLocators) != 1 {
|
||||
t.Fatalf("expected synthesized single locator, got %#v", resp.Profile.SecretLocators)
|
||||
}
|
||||
if resp.Profile.SecretLocators[0].Provider != "vault" || resp.Profile.SecretLocators[0].Target != store.XWorkmateSecretLocatorTargetOpenclawGatewayToken {
|
||||
t.Fatalf("expected synthesized openclaw vault locator, got %#v", resp.Profile.SecretLocators[0])
|
||||
if resp.Profile.SecretLocators[0].Provider != "vault" || resp.Profile.SecretLocators[0].Target != store.XWorkmateSecretLocatorTargetBridgeAuthToken {
|
||||
t.Fatalf("expected synthesized bridge vault locator, got %#v", resp.Profile.SecretLocators[0])
|
||||
}
|
||||
if resp.Profile.VaultSecretPath != "kv/openclaw" || resp.Profile.VaultSecretKey != "token" {
|
||||
t.Fatalf("expected legacy fields to remain readable, got %#v", resp.Profile)
|
||||
@ -472,17 +472,17 @@ func TestGetXWorkmateProfileFallsBackWhenVaultStatusReadFails(t *testing.T) {
|
||||
)
|
||||
body, err := json.Marshal(map[string]any{
|
||||
"profile": map[string]any{
|
||||
"openclawUrl": "wss://gateway.example.com",
|
||||
"openclawOrigin": "https://gateway.example.com",
|
||||
"vaultUrl": "https://vault.example.com",
|
||||
"vaultNamespace": "team-a",
|
||||
"BRIDGE_SERVER_URL": "wss://gateway.example.com",
|
||||
"bridgeServerOrigin": "https://gateway.example.com",
|
||||
"vaultUrl": "https://vault.example.com",
|
||||
"vaultNamespace": "team-a",
|
||||
"secretLocators": []map[string]any{
|
||||
{
|
||||
"id": "locator-openclaw",
|
||||
"provider": "vault",
|
||||
"secretPath": "kv/openclaw",
|
||||
"secretKey": "token",
|
||||
"target": store.XWorkmateSecretLocatorTargetOpenclawGatewayToken,
|
||||
"target": store.XWorkmateSecretLocatorTargetBridgeAuthToken,
|
||||
"required": true,
|
||||
},
|
||||
},
|
||||
@ -513,23 +513,23 @@ func TestGetXWorkmateProfileFallsBackWhenVaultStatusReadFails(t *testing.T) {
|
||||
|
||||
var resp struct {
|
||||
Profile struct {
|
||||
OpenclawURL string `json:"openclawUrl"`
|
||||
BridgeServerURL string `json:"BRIDGE_SERVER_URL"`
|
||||
} `json:"profile"`
|
||||
TokenConfigured struct {
|
||||
Openclaw bool `json:"openclaw"`
|
||||
Vault bool `json:"vault"`
|
||||
Apisix bool `json:"apisix"`
|
||||
Bridge bool `json:"bridge"`
|
||||
Vault bool `json:"vault"`
|
||||
Apisix bool `json:"apisix"`
|
||||
} `json:"tokenConfigured"`
|
||||
}
|
||||
if err := json.Unmarshal(getRec.Body.Bytes(), &resp); err != nil {
|
||||
t.Fatalf("decode profile response: %v", err)
|
||||
}
|
||||
|
||||
if resp.Profile.OpenclawURL != "wss://gateway.example.com" {
|
||||
if resp.Profile.BridgeServerURL != "wss://gateway.example.com" {
|
||||
t.Fatalf("expected profile payload to survive vault read failure, got %#v", resp.Profile)
|
||||
}
|
||||
if !resp.TokenConfigured.Openclaw {
|
||||
t.Fatalf("expected locator-derived openclaw tokenConfigured fallback, got %#v", resp.TokenConfigured)
|
||||
if !resp.TokenConfigured.Bridge {
|
||||
t.Fatalf("expected locator-derived bridge tokenConfigured fallback, got %#v", resp.TokenConfigured)
|
||||
}
|
||||
if resp.TokenConfigured.Vault {
|
||||
t.Fatalf("expected vault tokenConfigured fallback to stay false, got %#v", resp.TokenConfigured)
|
||||
@ -580,7 +580,7 @@ func TestUpdateXWorkmateProfileRejectsNestedRawTokenFields(t *testing.T) {
|
||||
|
||||
body, err := json.Marshal(map[string]any{
|
||||
"profile": map[string]any{
|
||||
"openclawUrl": "wss://gateway.example.com",
|
||||
"BRIDGE_SERVER_URL": "wss://gateway.example.com",
|
||||
"security": map[string]any{
|
||||
"gatewayToken": "secret-value",
|
||||
},
|
||||
@ -618,11 +618,11 @@ func TestXWorkmateSecretsWriteReadDeleteAndKeepLocatorMetadata(t *testing.T) {
|
||||
router, _, token := newXWorkmateTestHarness(t)
|
||||
profileBody, err := json.Marshal(map[string]any{
|
||||
"profile": map[string]any{
|
||||
"openclawUrl": "wss://gateway.example.com",
|
||||
"openclawOrigin": "https://gateway.example.com",
|
||||
"vaultUrl": "https://vault.example.com",
|
||||
"vaultNamespace": "team-a",
|
||||
"apisixUrl": "https://apigw.example.com",
|
||||
"BRIDGE_SERVER_URL": "wss://gateway.example.com",
|
||||
"bridgeServerOrigin": "https://gateway.example.com",
|
||||
"vaultUrl": "https://vault.example.com",
|
||||
"vaultNamespace": "team-a",
|
||||
"apisixUrl": "https://apigw.example.com",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
@ -640,7 +640,7 @@ func TestXWorkmateSecretsWriteReadDeleteAndKeepLocatorMetadata(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, target := range []string{
|
||||
store.XWorkmateSecretLocatorTargetOpenclawGatewayToken,
|
||||
store.XWorkmateSecretLocatorTargetBridgeAuthToken,
|
||||
store.XWorkmateSecretLocatorTargetVaultRootToken,
|
||||
store.XWorkmateSecretLocatorTargetAIGatewayAccessToken,
|
||||
} {
|
||||
@ -693,15 +693,15 @@ func TestXWorkmateSecretsWriteReadDeleteAndKeepLocatorMetadata(t *testing.T) {
|
||||
} `json:"secretLocators"`
|
||||
} `json:"profile"`
|
||||
TokenConfigured struct {
|
||||
Openclaw bool `json:"openclaw"`
|
||||
Vault bool `json:"vault"`
|
||||
Apisix bool `json:"apisix"`
|
||||
Bridge bool `json:"bridge"`
|
||||
Vault bool `json:"vault"`
|
||||
Apisix bool `json:"apisix"`
|
||||
} `json:"tokenConfigured"`
|
||||
}
|
||||
if err := json.Unmarshal(getProfileRec.Body.Bytes(), &profileResp); err != nil {
|
||||
t.Fatalf("decode profile response: %v", err)
|
||||
}
|
||||
if !profileResp.TokenConfigured.Openclaw || !profileResp.TokenConfigured.Vault || !profileResp.TokenConfigured.Apisix {
|
||||
if !profileResp.TokenConfigured.Bridge || !profileResp.TokenConfigured.Vault || !profileResp.TokenConfigured.Apisix {
|
||||
t.Fatalf("expected all synced tokenConfigured fields true, got %#v", profileResp.TokenConfigured)
|
||||
}
|
||||
if len(profileResp.Profile.SecretLocators) != 3 {
|
||||
@ -711,7 +711,7 @@ func TestXWorkmateSecretsWriteReadDeleteAndKeepLocatorMetadata(t *testing.T) {
|
||||
t.Fatalf("expected openclaw legacy compatibility fields to remain readable, got %#v", profileResp.Profile)
|
||||
}
|
||||
|
||||
deleteReq := httptest.NewRequest(http.MethodDelete, "/api/auth/xworkmate/secrets/"+store.XWorkmateSecretLocatorTargetOpenclawGatewayToken, nil)
|
||||
deleteReq := httptest.NewRequest(http.MethodDelete, "/api/auth/xworkmate/secrets/"+store.XWorkmateSecretLocatorTargetBridgeAuthToken, nil)
|
||||
deleteReq.Header.Set("Authorization", "Bearer "+token)
|
||||
deleteReq.Header.Set("X-Forwarded-Host", store.SharedXWorkmateDomain)
|
||||
deleteRec := httptest.NewRecorder()
|
||||
@ -736,16 +736,16 @@ func TestXWorkmateSecretsWriteReadDeleteAndKeepLocatorMetadata(t *testing.T) {
|
||||
} `json:"secretLocators"`
|
||||
} `json:"profile"`
|
||||
TokenConfigured struct {
|
||||
Openclaw bool `json:"openclaw"`
|
||||
Vault bool `json:"vault"`
|
||||
Apisix bool `json:"apisix"`
|
||||
Bridge bool `json:"bridge"`
|
||||
Vault bool `json:"vault"`
|
||||
Apisix bool `json:"apisix"`
|
||||
} `json:"tokenConfigured"`
|
||||
}
|
||||
if err := json.Unmarshal(getProfileAfterDeleteRec.Body.Bytes(), &afterDeleteResp); err != nil {
|
||||
t.Fatalf("decode post-delete profile response: %v", err)
|
||||
}
|
||||
if afterDeleteResp.TokenConfigured.Openclaw {
|
||||
t.Fatalf("expected deleted openclaw secret to report missing, got %#v", afterDeleteResp.TokenConfigured)
|
||||
if afterDeleteResp.TokenConfigured.Bridge {
|
||||
t.Fatalf("expected deleted bridge secret to report missing, got %#v", afterDeleteResp.TokenConfigured)
|
||||
}
|
||||
if !afterDeleteResp.TokenConfigured.Vault || !afterDeleteResp.TokenConfigured.Apisix {
|
||||
t.Fatalf("expected unrelated secret statuses to remain true, got %#v", afterDeleteResp.TokenConfigured)
|
||||
@ -772,7 +772,7 @@ func TestXWorkmateSharedSecretsRequireAdminMembershipForWrites(t *testing.T) {
|
||||
t.Fatalf("marshal secret payload: %v", err)
|
||||
}
|
||||
|
||||
req := httptest.NewRequest(http.MethodPut, "/api/auth/xworkmate/secrets/"+store.XWorkmateSecretLocatorTargetOpenclawGatewayToken, bytes.NewReader(body))
|
||||
req := httptest.NewRequest(http.MethodPut, "/api/auth/xworkmate/secrets/"+store.XWorkmateSecretLocatorTargetBridgeAuthToken, bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
req.Header.Set("X-Forwarded-Host", store.SharedXWorkmateDomain)
|
||||
@ -867,7 +867,7 @@ func TestXWorkmatePrivateSecretsAreScopedPerUser(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("marshal secret payload: %v", err)
|
||||
}
|
||||
writeReq := httptest.NewRequest(http.MethodPut, "/api/auth/xworkmate/secrets/"+store.XWorkmateSecretLocatorTargetOpenclawGatewayToken, bytes.NewReader(body))
|
||||
writeReq := httptest.NewRequest(http.MethodPut, "/api/auth/xworkmate/secrets/"+store.XWorkmateSecretLocatorTargetBridgeAuthToken, bytes.NewReader(body))
|
||||
writeReq.Header.Set("Content-Type", "application/json")
|
||||
writeReq.Header.Set("Authorization", "Bearer "+tokenA)
|
||||
writeReq.Header.Set("X-Forwarded-Host", "tenant-private-1.svc.plus")
|
||||
@ -897,25 +897,25 @@ func TestXWorkmatePrivateSecretsAreScopedPerUser(t *testing.T) {
|
||||
|
||||
var userAResp struct {
|
||||
TokenConfigured struct {
|
||||
Openclaw bool `json:"openclaw"`
|
||||
Bridge bool `json:"bridge"`
|
||||
} `json:"tokenConfigured"`
|
||||
}
|
||||
if err := json.Unmarshal(getARec.Body.Bytes(), &userAResp); err != nil {
|
||||
t.Fatalf("decode user A profile response: %v", err)
|
||||
}
|
||||
if !userAResp.TokenConfigured.Openclaw {
|
||||
if !userAResp.TokenConfigured.Bridge {
|
||||
t.Fatalf("expected user A secret to be configured, got %#v", userAResp.TokenConfigured)
|
||||
}
|
||||
|
||||
var userBResp struct {
|
||||
TokenConfigured struct {
|
||||
Openclaw bool `json:"openclaw"`
|
||||
Bridge bool `json:"bridge"`
|
||||
} `json:"tokenConfigured"`
|
||||
}
|
||||
if err := json.Unmarshal(getBRec.Body.Bytes(), &userBResp); err != nil {
|
||||
t.Fatalf("decode user B profile response: %v", err)
|
||||
}
|
||||
if userBResp.TokenConfigured.Openclaw {
|
||||
if userBResp.TokenConfigured.Bridge {
|
||||
t.Fatalf("expected user B to remain isolated from user A secret, got %#v", userBResp.TokenConfigured)
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,9 +54,9 @@ type xworkmateManagedSecretTarget struct {
|
||||
|
||||
var xworkmateManagedSecretTargets = []xworkmateManagedSecretTarget{
|
||||
{
|
||||
Target: store.XWorkmateSecretLocatorTargetOpenclawGatewayToken,
|
||||
Target: store.XWorkmateSecretLocatorTargetBridgeAuthToken,
|
||||
Required: true,
|
||||
TokenConfiguredID: "openclaw",
|
||||
TokenConfiguredID: "bridge",
|
||||
},
|
||||
{
|
||||
Target: store.XWorkmateSecretLocatorTargetVaultRootToken,
|
||||
|
||||
@ -56,20 +56,20 @@ type TenantMembership struct {
|
||||
func (TenantMembership) TableName() string { return "tenant_memberships" }
|
||||
|
||||
type XWorkmateProfile struct {
|
||||
ID string `gorm:"column:id;type:text;primaryKey"`
|
||||
TenantID string `gorm:"column:tenant_id;type:text;not null;uniqueIndex:idx_xworkmate_profiles_scope"`
|
||||
UserID string `gorm:"column:user_id;type:text;not null;default:'';uniqueIndex:idx_xworkmate_profiles_scope"`
|
||||
Scope string `gorm:"column:scope;type:text;not null;uniqueIndex:idx_xworkmate_profiles_scope"`
|
||||
OpenclawURL string `gorm:"column:openclaw_url;type:text;not null;default:''"`
|
||||
OpenclawOrigin string `gorm:"column:openclaw_origin;type:text;not null;default:''"`
|
||||
VaultURL string `gorm:"column:vault_url;type:text;not null;default:''"`
|
||||
VaultNamespace string `gorm:"column:vault_namespace;type:text;not null;default:''"`
|
||||
VaultSecretPath string `gorm:"column:vault_secret_path;type:text;not null;default:''"`
|
||||
VaultSecretKey string `gorm:"column:vault_secret_key;type:text;not null;default:''"`
|
||||
SecretLocators []XWorkmateSecretLocator `gorm:"column:secret_locators;type:text;not null;serializer:json;default:'[]'"`
|
||||
ApisixURL string `gorm:"column:apisix_url;type:text;not null;default:''"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;not null;autoCreateTime"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;not null;autoUpdateTime"`
|
||||
ID string `gorm:"column:id;type:text;primaryKey"`
|
||||
TenantID string `gorm:"column:tenant_id;type:text;not null;uniqueIndex:idx_xworkmate_profiles_scope"`
|
||||
UserID string `gorm:"column:user_id;type:text;not null;default:'';uniqueIndex:idx_xworkmate_profiles_scope"`
|
||||
Scope string `gorm:"column:scope;type:text;not null;uniqueIndex:idx_xworkmate_profiles_scope"`
|
||||
BridgeServerURL string `gorm:"column:openclaw_url;type:text;not null;default:''"`
|
||||
BridgeServerOrigin string `gorm:"column:openclaw_origin;type:text;not null;default:''"`
|
||||
VaultURL string `gorm:"column:vault_url;type:text;not null;default:''"`
|
||||
VaultNamespace string `gorm:"column:vault_namespace;type:text;not null;default:''"`
|
||||
VaultSecretPath string `gorm:"column:vault_secret_path;type:text;not null;default:''"`
|
||||
VaultSecretKey string `gorm:"column:vault_secret_key;type:text;not null;default:''"`
|
||||
SecretLocators []XWorkmateSecretLocator `gorm:"column:secret_locators;type:text;not null;serializer:json;default:'[]'"`
|
||||
ApisixURL string `gorm:"column:apisix_url;type:text;not null;default:''"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;not null;autoCreateTime"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;not null;autoUpdateTime"`
|
||||
}
|
||||
|
||||
type XWorkmateSecretLocator struct {
|
||||
|
||||
@ -32,7 +32,7 @@ const (
|
||||
|
||||
XWorkmateSecretLocatorProviderVault = "vault"
|
||||
|
||||
XWorkmateSecretLocatorTargetOpenclawGatewayToken = "openclaw.gateway_token"
|
||||
XWorkmateSecretLocatorTargetBridgeAuthToken = "bridge.auth_token"
|
||||
XWorkmateSecretLocatorTargetVaultRootToken = "vault.root_token"
|
||||
XWorkmateSecretLocatorTargetAIGatewayAccessToken = "ai_gateway.access_token"
|
||||
XWorkmateSecretLocatorTargetOllamaCloudAPIKey = "ollama_cloud.api_key"
|
||||
@ -79,20 +79,20 @@ type TenantMembership struct {
|
||||
}
|
||||
|
||||
type XWorkmateProfile struct {
|
||||
ID string
|
||||
TenantID string
|
||||
UserID string
|
||||
Scope string
|
||||
OpenclawURL string
|
||||
OpenclawOrigin string
|
||||
VaultURL string
|
||||
VaultNamespace string
|
||||
VaultSecretPath string
|
||||
VaultSecretKey string
|
||||
SecretLocators []XWorkmateSecretLocator
|
||||
ApisixURL string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
ID string
|
||||
TenantID string
|
||||
UserID string
|
||||
Scope string
|
||||
BridgeServerURL string
|
||||
BridgeServerOrigin string
|
||||
VaultURL string
|
||||
VaultNamespace string
|
||||
VaultSecretPath string
|
||||
VaultSecretKey string
|
||||
SecretLocators []XWorkmateSecretLocator
|
||||
ApisixURL string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
type XWorkmateSecretLocator struct {
|
||||
@ -179,7 +179,7 @@ func cloneXWorkmateSecretLocators(locators []XWorkmateSecretLocator) []XWorkmate
|
||||
|
||||
func legacyXWorkmateSecretLocatorID(profile *XWorkmateProfile) string {
|
||||
if profile == nil {
|
||||
return "legacy|xworkmate|openclaw.gateway_token"
|
||||
return "legacy|xworkmate|bridge.auth_token"
|
||||
}
|
||||
|
||||
return strings.Join([]string{
|
||||
@ -187,7 +187,7 @@ func legacyXWorkmateSecretLocatorID(profile *XWorkmateProfile) string {
|
||||
strings.TrimSpace(profile.TenantID),
|
||||
strings.TrimSpace(profile.UserID),
|
||||
NormalizeXWorkmateProfileScope(profile.Scope),
|
||||
XWorkmateSecretLocatorTargetOpenclawGatewayToken,
|
||||
XWorkmateSecretLocatorTargetBridgeAuthToken,
|
||||
}, "|")
|
||||
}
|
||||
|
||||
@ -197,13 +197,13 @@ func synthesizeXWorkmateSecretLocatorFromLegacy(profile *XWorkmateProfile) XWork
|
||||
Provider: XWorkmateSecretLocatorProviderVault,
|
||||
SecretPath: profile.VaultSecretPath,
|
||||
SecretKey: profile.VaultSecretKey,
|
||||
Target: XWorkmateSecretLocatorTargetOpenclawGatewayToken,
|
||||
Target: XWorkmateSecretLocatorTargetBridgeAuthToken,
|
||||
}
|
||||
}
|
||||
|
||||
func compatibilityXWorkmateSecretLocator(locators []XWorkmateSecretLocator) (string, string, bool) {
|
||||
for _, locator := range locators {
|
||||
if locator.Target == XWorkmateSecretLocatorTargetOpenclawGatewayToken &&
|
||||
if locator.Target == XWorkmateSecretLocatorTargetBridgeAuthToken &&
|
||||
locator.SecretPath != "" && locator.SecretKey != "" {
|
||||
return locator.SecretPath, locator.SecretKey, true
|
||||
}
|
||||
@ -292,8 +292,8 @@ func NormalizeXWorkmateProfile(profile *XWorkmateProfile) {
|
||||
profile.TenantID = strings.TrimSpace(profile.TenantID)
|
||||
profile.UserID = strings.TrimSpace(profile.UserID)
|
||||
profile.Scope = NormalizeXWorkmateProfileScope(profile.Scope)
|
||||
profile.OpenclawURL = strings.TrimSpace(profile.OpenclawURL)
|
||||
profile.OpenclawOrigin = strings.TrimSpace(profile.OpenclawOrigin)
|
||||
profile.BridgeServerURL = strings.TrimSpace(profile.BridgeServerURL)
|
||||
profile.BridgeServerOrigin = strings.TrimSpace(profile.BridgeServerOrigin)
|
||||
profile.VaultURL = strings.TrimSpace(profile.VaultURL)
|
||||
profile.VaultNamespace = strings.TrimSpace(profile.VaultNamespace)
|
||||
profile.VaultSecretPath = strings.Trim(strings.TrimSpace(profile.VaultSecretPath), "/")
|
||||
|
||||
@ -290,8 +290,8 @@ func (s *memoryStore) UpsertXWorkmateProfile(ctx context.Context, profile *XWork
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if existing, ok := s.xworkmateProfiles[key]; ok {
|
||||
existing.OpenclawURL = profile.OpenclawURL
|
||||
existing.OpenclawOrigin = profile.OpenclawOrigin
|
||||
existing.BridgeServerURL = profile.BridgeServerURL
|
||||
existing.BridgeServerOrigin = profile.BridgeServerOrigin
|
||||
existing.VaultURL = profile.VaultURL
|
||||
existing.VaultNamespace = profile.VaultNamespace
|
||||
existing.VaultSecretPath = profile.VaultSecretPath
|
||||
@ -305,20 +305,20 @@ func (s *memoryStore) UpsertXWorkmateProfile(ctx context.Context, profile *XWork
|
||||
}
|
||||
|
||||
stored := &XWorkmateProfile{
|
||||
ID: profile.ID,
|
||||
TenantID: profile.TenantID,
|
||||
UserID: profile.UserID,
|
||||
Scope: profile.Scope,
|
||||
OpenclawURL: profile.OpenclawURL,
|
||||
OpenclawOrigin: profile.OpenclawOrigin,
|
||||
VaultURL: profile.VaultURL,
|
||||
VaultNamespace: profile.VaultNamespace,
|
||||
VaultSecretPath: profile.VaultSecretPath,
|
||||
VaultSecretKey: profile.VaultSecretKey,
|
||||
SecretLocators: cloneXWorkmateSecretLocators(profile.SecretLocators),
|
||||
ApisixURL: profile.ApisixURL,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
ID: profile.ID,
|
||||
TenantID: profile.TenantID,
|
||||
UserID: profile.UserID,
|
||||
Scope: profile.Scope,
|
||||
BridgeServerURL: profile.BridgeServerURL,
|
||||
BridgeServerOrigin: profile.BridgeServerOrigin,
|
||||
VaultURL: profile.VaultURL,
|
||||
VaultNamespace: profile.VaultNamespace,
|
||||
VaultSecretPath: profile.VaultSecretPath,
|
||||
VaultSecretKey: profile.VaultSecretKey,
|
||||
SecretLocators: cloneXWorkmateSecretLocators(profile.SecretLocators),
|
||||
ApisixURL: profile.ApisixURL,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
s.xworkmateProfiles[key] = stored
|
||||
profile.CreatedAt = stored.CreatedAt
|
||||
|
||||
@ -242,8 +242,8 @@ LIMIT 1`
|
||||
&profile.TenantID,
|
||||
&profile.UserID,
|
||||
&profile.Scope,
|
||||
&profile.OpenclawURL,
|
||||
&profile.OpenclawOrigin,
|
||||
&profile.BridgeServerURL,
|
||||
&profile.BridgeServerOrigin,
|
||||
&profile.VaultURL,
|
||||
&profile.VaultNamespace,
|
||||
&profile.VaultSecretPath,
|
||||
@ -304,8 +304,8 @@ RETURNING created_at, updated_at`
|
||||
profile.TenantID,
|
||||
profile.UserID,
|
||||
profile.Scope,
|
||||
profile.OpenclawURL,
|
||||
profile.OpenclawOrigin,
|
||||
profile.BridgeServerURL,
|
||||
profile.BridgeServerOrigin,
|
||||
profile.VaultURL,
|
||||
profile.VaultNamespace,
|
||||
profile.VaultSecretPath,
|
||||
|
||||
@ -87,7 +87,7 @@ func TestMemoryStoreResolveTenantAndProfile(t *testing.T) {
|
||||
TenantID: privateTenant.ID,
|
||||
UserID: "user-1",
|
||||
Scope: XWorkmateProfileScopeUserPrivate,
|
||||
OpenclawURL: "wss://openclaw.tenant-one.svc.plus",
|
||||
BridgeServerURL: "wss://openclaw.tenant-one.svc.plus",
|
||||
VaultSecretPath: "kv/openclaw",
|
||||
VaultSecretKey: "token",
|
||||
}); err != nil {
|
||||
@ -109,8 +109,8 @@ func TestMemoryStoreResolveTenantAndProfile(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("get private profile: %v", err)
|
||||
}
|
||||
if profile.OpenclawURL != "wss://openclaw.tenant-one.svc.plus" {
|
||||
t.Fatalf("expected persisted openclaw url, got %q", profile.OpenclawURL)
|
||||
if profile.BridgeServerURL != "wss://openclaw.tenant-one.svc.plus" {
|
||||
t.Fatalf("expected persisted bridge server url, got %q", profile.BridgeServerURL)
|
||||
}
|
||||
if profile.VaultSecretPath != "kv/openclaw" || profile.VaultSecretKey != "token" {
|
||||
t.Fatalf("expected legacy secret fields to round-trip, got %#v", profile)
|
||||
@ -121,8 +121,8 @@ func TestMemoryStoreResolveTenantAndProfile(t *testing.T) {
|
||||
if profile.SecretLocators[0].Provider != XWorkmateSecretLocatorProviderVault {
|
||||
t.Fatalf("expected vault provider, got %#v", profile.SecretLocators[0])
|
||||
}
|
||||
if profile.SecretLocators[0].Target != XWorkmateSecretLocatorTargetOpenclawGatewayToken {
|
||||
t.Fatalf("expected openclaw target, got %#v", profile.SecretLocators[0])
|
||||
if profile.SecretLocators[0].Target != XWorkmateSecretLocatorTargetBridgeAuthToken {
|
||||
t.Fatalf("expected bridge auth token target, got %#v", profile.SecretLocators[0])
|
||||
}
|
||||
if profile.SecretLocators[0].SecretPath != "kv/openclaw" || profile.SecretLocators[0].SecretKey != "token" {
|
||||
t.Fatalf("expected synthesized secret locator path/key, got %#v", profile.SecretLocators[0])
|
||||
@ -158,7 +158,7 @@ func TestMemoryStorePersistsExplicitSecretLocators(t *testing.T) {
|
||||
Provider: "vault",
|
||||
SecretPath: "kv/openclaw",
|
||||
SecretKey: "gateway-token",
|
||||
Target: XWorkmateSecretLocatorTargetOpenclawGatewayToken,
|
||||
Target: XWorkmateSecretLocatorTargetBridgeAuthToken,
|
||||
Required: true,
|
||||
},
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user