ScuttleBot

fix: nil topology manager panic on agent registration A nil *topology.Manager passed as the topologyManager interface is non-nil in Go (nil interface trap). setAgentModes checked s.topoMgr == nil but it was a non-nil interface wrapping a nil pointer, so GrantAccess panicked. Fix: pass an explicit nil interface from main.go when topology is not configured.

lmata 2026-04-04 19:36 trunk
Commit 02e882291b0b71ceb8306f1e8c05665f4658e66427e65879ee6bba55530b8ece
--- cmd/scuttlebot/main.go
+++ cmd/scuttlebot/main.go
@@ -345,11 +345,18 @@
345345
// Start HTTP REST API server.
346346
var llmCfg *config.LLMConfig
347347
if len(cfg.LLM.Backends) > 0 {
348348
llmCfg = &cfg.LLM
349349
}
350
- apiSrv := api.New(reg, tokens, bridgeBot, policyStore, adminStore, llmCfg, topoMgr, cfgStore, cfg.TLS.Domain, log)
350
+ // Pass an explicit nil interface when topology is not configured.
351
+ // A nil *topology.Manager passed as a topologyManager interface is
352
+ // non-nil (Go nil interface trap) and causes panics in setAgentModes.
353
+ var topoIface api.TopologyManager
354
+ if topoMgr != nil {
355
+ topoIface = topoMgr
356
+ }
357
+ apiSrv := api.New(reg, tokens, bridgeBot, policyStore, adminStore, llmCfg, topoIface, cfgStore, cfg.TLS.Domain, log)
351358
handler := apiSrv.Handler()
352359
353360
var httpServer, tlsServer *http.Server
354361
355362
if cfg.TLS.Domain != "" {
356363
--- cmd/scuttlebot/main.go
+++ cmd/scuttlebot/main.go
@@ -345,11 +345,18 @@
345 // Start HTTP REST API server.
346 var llmCfg *config.LLMConfig
347 if len(cfg.LLM.Backends) > 0 {
348 llmCfg = &cfg.LLM
349 }
350 apiSrv := api.New(reg, tokens, bridgeBot, policyStore, adminStore, llmCfg, topoMgr, cfgStore, cfg.TLS.Domain, log)
 
 
 
 
 
 
 
351 handler := apiSrv.Handler()
352
353 var httpServer, tlsServer *http.Server
354
355 if cfg.TLS.Domain != "" {
356
--- cmd/scuttlebot/main.go
+++ cmd/scuttlebot/main.go
@@ -345,11 +345,18 @@
345 // Start HTTP REST API server.
346 var llmCfg *config.LLMConfig
347 if len(cfg.LLM.Backends) > 0 {
348 llmCfg = &cfg.LLM
349 }
350 // Pass an explicit nil interface when topology is not configured.
351 // A nil *topology.Manager passed as a topologyManager interface is
352 // non-nil (Go nil interface trap) and causes panics in setAgentModes.
353 var topoIface api.TopologyManager
354 if topoMgr != nil {
355 topoIface = topoMgr
356 }
357 apiSrv := api.New(reg, tokens, bridgeBot, policyStore, adminStore, llmCfg, topoIface, cfgStore, cfg.TLS.Domain, log)
358 handler := apiSrv.Handler()
359
360 var httpServer, tlsServer *http.Server
361
362 if cfg.TLS.Domain != "" {
363
--- internal/api/channels_topology.go
+++ internal/api/channels_topology.go
@@ -5,16 +5,19 @@
55
"net/http"
66
77
"github.com/conflicthq/scuttlebot/internal/topology"
88
)
99
10
-// topologyManager is the interface the API server uses to provision channels
10
+// TopologyManager is the interface the API server uses to provision channels
1111
// and query the channel policy. Satisfied by *topology.Manager.
12
+type TopologyManager = topologyManager
1213
type topologyManager interface {
1314
ProvisionChannel(ch topology.ChannelConfig) error
1415
DropChannel(channel string)
1516
Policy() *topology.Policy
17
+ GrantAccess(nick, channel, level string)
18
+ RevokeAccess(nick, channel string)
1619
}
1720
1821
type provisionChannelRequest struct {
1922
Name string `json:"name"`
2023
Topic string `json:"topic,omitempty"`
2124
--- internal/api/channels_topology.go
+++ internal/api/channels_topology.go
@@ -5,16 +5,19 @@
5 "net/http"
6
7 "github.com/conflicthq/scuttlebot/internal/topology"
8 )
9
10 // topologyManager is the interface the API server uses to provision channels
11 // and query the channel policy. Satisfied by *topology.Manager.
 
12 type topologyManager interface {
13 ProvisionChannel(ch topology.ChannelConfig) error
14 DropChannel(channel string)
15 Policy() *topology.Policy
 
 
16 }
17
18 type provisionChannelRequest struct {
19 Name string `json:"name"`
20 Topic string `json:"topic,omitempty"`
21
--- internal/api/channels_topology.go
+++ internal/api/channels_topology.go
@@ -5,16 +5,19 @@
5 "net/http"
6
7 "github.com/conflicthq/scuttlebot/internal/topology"
8 )
9
10 // TopologyManager is the interface the API server uses to provision channels
11 // and query the channel policy. Satisfied by *topology.Manager.
12 type TopologyManager = topologyManager
13 type topologyManager interface {
14 ProvisionChannel(ch topology.ChannelConfig) error
15 DropChannel(channel string)
16 Policy() *topology.Policy
17 GrantAccess(nick, channel, level string)
18 RevokeAccess(nick, channel string)
19 }
20
21 type provisionChannelRequest struct {
22 Name string `json:"name"`
23 Topic string `json:"topic,omitempty"`
24

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button