Skip to content

Commit 581df54

Browse files
gcmsgclaude
andcommitted
fix: enforce JWT secret, add connection pool, tighten auth window
- SRV-02: Reject startup when jwt_secret is empty and auth.required=true - SRV-03: Configure DB connection pool (MaxOpenConns=25, MaxIdleConns=5, ConnMaxLifetime=30m) for both SQLite and PostgreSQL - SRV-04: Reduce signaling auth frame replay window from 30s to 5s - SRV-09: Increase Redis Pub/Sub buffer from 256 to 4096 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 523879f commit 581df54

File tree

5 files changed

+17
-3
lines changed

5 files changed

+17
-3
lines changed

cmd/peerclawd/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ func main() {
132132

133133
jwtSecret := cfg.UserAuth.JWTSecret
134134
if jwtSecret == "" {
135+
if cfg.Auth.Required {
136+
logger.Error("user_auth.jwt_secret must be set when auth.required=true")
137+
os.Exit(1)
138+
}
135139
jwtSecret = "peerclaw-dev-secret-change-me"
136140
logger.Warn("using default JWT secret — set user_auth.jwt_secret in config for production")
137141
}

internal/registry/postgres.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ func NewPostgresStore(dsn string) (*PostgresStore, error) {
2828
_ = db.Close()
2929
return nil, fmt.Errorf("ping postgres: %w", err)
3030
}
31+
// Configure connection pool for production workloads.
32+
db.SetMaxOpenConns(25)
33+
db.SetMaxIdleConns(5)
34+
db.SetConnMaxLifetime(30 * time.Minute)
35+
3136
s := &PostgresStore{db: db}
3237
if err := s.migrate(); err != nil {
3338
_ = db.Close()

internal/registry/sqlite.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ func NewSQLiteStore(dsn string) (*SQLiteStore, error) {
3030
_ = db.Close()
3131
return nil, fmt.Errorf("set WAL mode: %w", err)
3232
}
33+
// Configure connection pool for production workloads.
34+
db.SetMaxOpenConns(25)
35+
db.SetMaxIdleConns(5)
36+
db.SetConnMaxLifetime(30 * time.Minute)
37+
3338
s := &SQLiteStore{db: db}
3439
if err := s.migrate(); err != nil {
3540
_ = db.Close()

internal/signaling/redis_broker.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func (b *RedisBroker) Subscribe(ctx context.Context) (<-chan signaling.SignalMes
6767
return nil, fmt.Errorf("redis subscribe: %w", err)
6868
}
6969

70-
ch := make(chan signaling.SignalMessage, 256)
70+
ch := make(chan signaling.SignalMessage, 4096)
7171
go func() {
7272
defer close(ch)
7373
defer pubsub.Close()

internal/signaling/ws.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,9 @@ func (h *Hub) authenticateConn(ctx context.Context, conn *websocket.Conn, expect
295295
return "", fmt.Errorf("agent_id mismatch: query=%s, frame=%s", expectedAgentID, frame.AgentID)
296296
}
297297

298-
// Verify timestamp is within 30 seconds to prevent replay.
298+
// Verify timestamp is within 5 seconds to prevent replay.
299299
now := time.Now().Unix()
300-
if abs64(now-frame.Timestamp) > 30 {
300+
if abs64(now-frame.Timestamp) > 5 {
301301
return "", fmt.Errorf("auth frame timestamp too old")
302302
}
303303

0 commit comments

Comments
 (0)