refactor(ws/heartbeat): accept agent_key or UUID via cache-aware resolver

All 7 heartbeat handlers (get/set/toggle/test/logs/checklistGet/checklistSet)
now accept either a UUID or an agent_key for params.agentId. Behavior
additive — existing UUID-only clients keep working.

Adds HeartbeatMethods.SetAgentRouter setter wired from cmd/gateway_methods.go
so the fast path avoids a DB roundtrip for cached agents. Preserves the
literal "invalid agentId" error string (no i18n key change).

Phase 3 of agent identity hardening.
This commit is contained in:
viettranx committed 2026-04-11 21:22:23 +07:00
1 parent 6c17aad8d7
commit 84babc1c3c
2 files changed
+21 -8

No files matched your search

+6 -1
View File
@@ -43,10 +43,15 @@ func registerAllMethods(server *gateway.Server, agents *agent.Router, sessStore
// Phase 2: Heartbeat
heartbeatMethods := methods.NewHeartbeatMethods(heartbeatStore, msgBus)
// Wire cache-aware resolver (Phase 3): accepts agent_key or UUID input
// without a DB roundtrip on the hot path when the agent is router-cached.
heartbeatMethods.SetAgentRouter(agents)
heartbeatMethods.Register(router)
// Phase 2: Config permissions
methods.NewConfigPermissionsMethods(configPermStore, agentStore).Register(router)
cfgPerms := methods.NewConfigPermissionsMethods(configPermStore, agentStore)
cfgPerms.SetAgentRouter(agents)
cfgPerms.Register(router)
// Phase 2: Pairing (store created externally, shared with channel manager).
// OnApprove callback is set later by the caller after channel manager is created.
+15 -7
View File
@@ -11,6 +11,7 @@ import (
"github.com/google/uuid"
"github.com/nextlevelbuilder/goclaw/internal/agent"
"github.com/nextlevelbuilder/goclaw/internal/bus"
"github.com/nextlevelbuilder/goclaw/internal/gateway"
"github.com/nextlevelbuilder/goclaw/internal/i18n"
@@ -22,6 +23,7 @@ import (
type HeartbeatMethods struct {
hbStore store.HeartbeatStore
agentStore store.AgentStore
agentRouter *agent.Router // cache-aware lookup for resolveAgentUUIDCached hot path
providerStore store.ProviderStore
eventBus bus.EventPublisher
wakeFn func(uuid.UUID) // triggers immediate heartbeat run
@@ -36,6 +38,12 @@ func (m *HeartbeatMethods) SetAgentStore(as store.AgentStore) {
m.agentStore = as
}
// SetAgentRouter wires the agent router for cache-aware agent_key resolution.
// Optional — when nil, resolveAgentUUIDCached falls back to a pure DB lookup.
func (m *HeartbeatMethods) SetAgentRouter(r *agent.Router) {
m.agentRouter = r
}
// SetProviderStore sets the provider store for resolving provider names to UUIDs.
func (m *HeartbeatMethods) SetProviderStore(ps store.ProviderStore) {
m.providerStore = ps
@@ -70,7 +78,7 @@ func (m *HeartbeatMethods) handleGet(ctx context.Context, client *gateway.Client
return
}
agentUUID, err := uuid.Parse(params.AgentID)
agentUUID, err := resolveAgentUUIDCached(ctx, m.agentRouter, m.agentStore, params.AgentID)
if err != nil {
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, "invalid agentId"))
return
@@ -116,7 +124,7 @@ func (m *HeartbeatMethods) handleSet(ctx context.Context, client *gateway.Client
return
}
agentUUID, err := uuid.Parse(params.AgentID)
agentUUID, err := resolveAgentUUIDCached(ctx, m.agentRouter, m.agentStore, params.AgentID)
if err != nil {
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, "invalid agentId"))
return
@@ -242,7 +250,7 @@ func (m *HeartbeatMethods) handleToggle(ctx context.Context, client *gateway.Cli
return
}
agentUUID, err := uuid.Parse(params.AgentID)
agentUUID, err := resolveAgentUUIDCached(ctx, m.agentRouter, m.agentStore, params.AgentID)
if err != nil {
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, "invalid agentId"))
return
@@ -290,7 +298,7 @@ func (m *HeartbeatMethods) handleTest(ctx context.Context, client *gateway.Clien
return
}
agentUUID, err := uuid.Parse(params.AgentID)
agentUUID, err := resolveAgentUUIDCached(ctx, m.agentRouter, m.agentStore, params.AgentID)
if err != nil {
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, "invalid agentId"))
return
@@ -325,7 +333,7 @@ func (m *HeartbeatMethods) handleLogs(ctx context.Context, client *gateway.Clien
return
}
agentUUID, err := uuid.Parse(params.AgentID)
agentUUID, err := resolveAgentUUIDCached(ctx, m.agentRouter, m.agentStore, params.AgentID)
if err != nil {
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, "invalid agentId"))
return
@@ -360,7 +368,7 @@ func (m *HeartbeatMethods) handleChecklistGet(ctx context.Context, client *gatew
return
}
agentUUID, err := uuid.Parse(params.AgentID)
agentUUID, err := resolveAgentUUIDCached(ctx, m.agentRouter, m.agentStore, params.AgentID)
if err != nil {
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, "invalid agentId"))
return
@@ -403,7 +411,7 @@ func (m *HeartbeatMethods) handleChecklistSet(ctx context.Context, client *gatew
return
}
agentUUID, err := uuid.Parse(params.AgentID)
agentUUID, err := resolveAgentUUIDCached(ctx, m.agentRouter, m.agentStore, params.AgentID)
if err != nil {
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, "invalid agentId"))
return