Changeset 0.9.4 (#54)
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/crypto"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/events"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/handlers"
|
||||
@@ -23,6 +24,8 @@ func main() {
|
||||
providers.Init()
|
||||
|
||||
var stores store.Stores
|
||||
uekCache := crypto.NewUEKCache()
|
||||
var keyResolver *crypto.KeyResolver
|
||||
|
||||
if err := database.Connect(cfg); err != nil {
|
||||
log.Printf("⚠ Database unavailable: %v", err)
|
||||
@@ -33,6 +36,28 @@ func main() {
|
||||
log.Fatalf("❌ Schema migration failed: %v", err)
|
||||
}
|
||||
|
||||
// Vault: enforce encryption key + backfill plaintext keys
|
||||
if err := crypto.EnforceEncryptionKey(database.DB, cfg.EncryptionKey); err != nil {
|
||||
log.Fatalf("❌ Vault check failed: %v", err)
|
||||
}
|
||||
if cfg.EncryptionKey != "" {
|
||||
if err := crypto.BackfillEncryptedKeys(database.DB, cfg.EncryptionKey); err != nil {
|
||||
log.Fatalf("❌ Vault backfill failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Derive env key for key resolver (nil if not set)
|
||||
var envKey []byte
|
||||
if cfg.EncryptionKey != "" {
|
||||
var err error
|
||||
envKey, err = crypto.DeriveKeyFromEnv(cfg.EncryptionKey)
|
||||
if err != nil {
|
||||
log.Fatalf("❌ Failed to derive encryption key: %v", err)
|
||||
}
|
||||
log.Println(" 🔐 API key encryption active")
|
||||
}
|
||||
keyResolver = crypto.NewKeyResolver(envKey, uekCache)
|
||||
|
||||
// Initialize store layer
|
||||
stores = postgres.NewStores(database.DB)
|
||||
|
||||
@@ -68,7 +93,7 @@ func main() {
|
||||
base.GET("/ws", middleware.Auth(cfg), hub.HandleWebSocket)
|
||||
|
||||
// ── Auth routes (rate limited) ──────────────
|
||||
auth := handlers.NewAuthHandler(cfg, stores)
|
||||
auth := handlers.NewAuthHandler(cfg, stores, uekCache)
|
||||
authLimiter := middleware.NewRateLimiter(1, 5)
|
||||
|
||||
api := base.Group("/api/v1")
|
||||
@@ -110,7 +135,7 @@ func main() {
|
||||
protected.DELETE("/channels/:id", channels.DeleteChannel)
|
||||
|
||||
// Messages
|
||||
msgs := handlers.NewMessageHandler()
|
||||
msgs := handlers.NewMessageHandler(keyResolver)
|
||||
protected.GET("/channels/:id/messages", msgs.ListMessages)
|
||||
protected.POST("/channels/:id/messages", msgs.CreateMessage)
|
||||
|
||||
@@ -122,11 +147,11 @@ func main() {
|
||||
protected.GET("/channels/:id/messages/:msgId/siblings", msgs.ListSiblings)
|
||||
|
||||
// Chat Completions
|
||||
comp := handlers.NewCompletionHandler()
|
||||
comp := handlers.NewCompletionHandler(keyResolver)
|
||||
protected.POST("/chat/completions", comp.Complete)
|
||||
|
||||
// Provider Configs (user-facing — replaces /api-configs)
|
||||
provCfg := handlers.NewProviderConfigHandler(stores)
|
||||
provCfg := handlers.NewProviderConfigHandler(stores, keyResolver)
|
||||
protected.GET("/api-configs", provCfg.ListConfigs) // backward compat
|
||||
protected.POST("/api-configs", provCfg.CreateConfig)
|
||||
protected.GET("/api-configs/:id", provCfg.GetConfig)
|
||||
@@ -177,7 +202,7 @@ func main() {
|
||||
protected.DELETE("/notes/:id", notes.Delete)
|
||||
|
||||
// Teams (user: my teams)
|
||||
teams := handlers.NewTeamHandler()
|
||||
teams := handlers.NewTeamHandler(keyResolver)
|
||||
protected.GET("/teams/mine", teams.MyTeams)
|
||||
|
||||
// Team admin self-service
|
||||
@@ -209,7 +234,7 @@ func main() {
|
||||
}
|
||||
|
||||
// Public global settings (non-admin users can read safe subset)
|
||||
adm := handlers.NewAdminHandler(stores)
|
||||
adm := handlers.NewAdminHandler(stores, keyResolver)
|
||||
protected.GET("/settings/public", adm.PublicSettings)
|
||||
}
|
||||
|
||||
@@ -218,7 +243,7 @@ func main() {
|
||||
admin.Use(middleware.Auth(cfg))
|
||||
admin.Use(middleware.RequireAdmin())
|
||||
{
|
||||
adm := handlers.NewAdminHandler(stores)
|
||||
adm := handlers.NewAdminHandler(stores, keyResolver)
|
||||
|
||||
// User management
|
||||
admin.GET("/users", adm.ListUsers)
|
||||
@@ -259,7 +284,7 @@ func main() {
|
||||
admin.DELETE("/presets/:id/avatar", handlers.DeletePresetAvatar)
|
||||
|
||||
// Teams (admin)
|
||||
teamAdm := handlers.NewTeamHandler()
|
||||
teamAdm := handlers.NewTeamHandler(keyResolver)
|
||||
admin.GET("/teams", teamAdm.ListTeams)
|
||||
admin.POST("/teams", teamAdm.CreateTeam)
|
||||
admin.GET("/teams/:id", teamAdm.GetTeam)
|
||||
|
||||
Reference in New Issue
Block a user