mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-07-25 04:20:16 +00:00
Squash merge PR #112 after resolving the project changelog conflict with current dev. Local checks passed: config gateway tests, provider/http/tools deny-pattern tests, go build ./..., and go build -tags sqliteonly ./.... PR CI run 26704832350 passed release-versioning, go, and web.
91 lines
2.9 KiB
Go
91 lines
2.9 KiB
Go
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
|
|
"github.com/nextlevelbuilder/goclaw/internal/bus"
|
|
"github.com/nextlevelbuilder/goclaw/internal/config"
|
|
"github.com/nextlevelbuilder/goclaw/internal/providers"
|
|
"github.com/nextlevelbuilder/goclaw/internal/store"
|
|
"github.com/nextlevelbuilder/goclaw/internal/tools"
|
|
)
|
|
|
|
// subscribeShellDenyGroupsReload wires pub/sub so global shell deny-group
|
|
// toggles applied via the /config page take effect without a process restart.
|
|
// Extracted from runLifecycle to make the dispatch path unit-testable
|
|
// (the regression coverage missing from the original PR #1005 attempt).
|
|
func subscribeShellDenyGroupsReload(msgBus *bus.MessageBus, toolsReg *tools.Registry) {
|
|
msgBus.Subscribe("shell-deny-groups-config-reload", func(evt bus.Event) {
|
|
if evt.Name != bus.TopicConfigChanged {
|
|
return
|
|
}
|
|
updatedCfg, ok := evt.Payload.(*config.Config)
|
|
if !ok {
|
|
return
|
|
}
|
|
snapshot := updatedCfg.Clone()
|
|
execTool, ok := toolsReg.Get("exec")
|
|
if !ok {
|
|
return
|
|
}
|
|
et, ok := execTool.(*tools.ExecTool)
|
|
if !ok {
|
|
return
|
|
}
|
|
et.SetGlobalShellDenyGroups(snapshot.Tools.ShellDenyGroups)
|
|
et.SetCommandKeywordAllowlist(snapshot.Tools.CommandKeywordAllowlist)
|
|
slog.Info("shell deny groups reloaded via pub/sub",
|
|
"groups", len(snapshot.Tools.ShellDenyGroups),
|
|
"command_keyword_allowlist_rules", len(snapshot.Tools.CommandKeywordAllowlist),
|
|
)
|
|
})
|
|
}
|
|
|
|
func subscribeProviderShellDenyGroupsReload(msgBus *bus.MessageBus, providerReg *providers.Registry, provStore store.ProviderStore, mcpStore store.MCPServerStore) {
|
|
if msgBus == nil || providerReg == nil {
|
|
return
|
|
}
|
|
msgBus.Subscribe("shell-deny-provider-policy-reload", func(evt bus.Event) {
|
|
if evt.Name != bus.TopicConfigChanged {
|
|
return
|
|
}
|
|
updatedCfg, ok := evt.Payload.(*config.Config)
|
|
if !ok {
|
|
return
|
|
}
|
|
reloadShellDenyProviderPolicies(providerReg, provStore, mcpStore, updatedCfg)
|
|
})
|
|
}
|
|
|
|
func reloadShellDenyProviderPolicies(providerReg *providers.Registry, provStore store.ProviderStore, mcpStore store.MCPServerStore, cfg *config.Config) {
|
|
if providerReg == nil || cfg == nil {
|
|
return
|
|
}
|
|
snapshot := cfg.Clone()
|
|
registerClaudeCLIFromConfig(providerReg, snapshot)
|
|
if snapshot.Providers.ACP.Binary != "" {
|
|
registerACPFromConfig(providerReg, snapshot.Providers.ACP, snapshot.ShellDenyGroupsSnapshot())
|
|
}
|
|
if provStore == nil {
|
|
return
|
|
}
|
|
dbProviders, err := provStore.ListAllProviders(context.Background())
|
|
if err != nil {
|
|
slog.Warn("shell deny provider policy reload: failed to load providers from DB", "error", err)
|
|
return
|
|
}
|
|
gatewayAddr := loopbackAddr(snapshot.Gateway.Host, snapshot.Gateway.Port)
|
|
for _, p := range dbProviders {
|
|
if !p.Enabled {
|
|
continue
|
|
}
|
|
switch p.ProviderType {
|
|
case store.ProviderClaudeCLI:
|
|
registerClaudeCLIFromDB(providerReg, p, gatewayAddr, snapshot.Gateway.Token, mcpStore, snapshot)
|
|
case store.ProviderACP:
|
|
registerACPFromDB(providerReg, p, snapshot.ShellDenyGroupsSnapshot())
|
|
}
|
|
}
|
|
}
|