Changeset 0.10.0 (#56)

This commit is contained in:
2026-02-24 14:50:53 +00:00
parent cdfd69bad3
commit ea03f956ca
31 changed files with 3303 additions and 167 deletions

View File

@@ -12,6 +12,7 @@ import (
"git.gobha.me/xcaliber/chat-switchboard/handlers"
"git.gobha.me/xcaliber/chat-switchboard/middleware"
"git.gobha.me/xcaliber/chat-switchboard/providers"
"git.gobha.me/xcaliber/chat-switchboard/roles"
"git.gobha.me/xcaliber/chat-switchboard/store"
postgres "git.gobha.me/xcaliber/chat-switchboard/store/postgres"
_ "git.gobha.me/xcaliber/chat-switchboard/tools" // registers built-in tools via init()
@@ -69,6 +70,9 @@ func main() {
}
defer database.Close()
// Role resolver for model role dispatch (needs stores + vault)
roleResolver := roles.NewResolver(stores, keyResolver)
r := gin.Default()
r.Use(middleware.CORS())
@@ -135,7 +139,7 @@ func main() {
protected.DELETE("/channels/:id", channels.DeleteChannel)
// Messages
msgs := handlers.NewMessageHandler(keyResolver)
msgs := handlers.NewMessageHandler(keyResolver, stores)
protected.GET("/channels/:id/messages", msgs.ListMessages)
protected.POST("/channels/:id/messages", msgs.CreateMessage)
@@ -147,7 +151,7 @@ func main() {
protected.GET("/channels/:id/messages/:msgId/siblings", msgs.ListSiblings)
// Chat Completions
comp := handlers.NewCompletionHandler(keyResolver)
comp := handlers.NewCompletionHandler(keyResolver, stores)
protected.POST("/chat/completions", comp.Complete)
// Provider Configs (user-facing — replaces /api-configs)
@@ -172,7 +176,7 @@ func main() {
protected.POST("/models/preferences/bulk", modelPrefs.BulkSetPreferences)
// User Settings & Profile
settings := handlers.NewSettingsHandler()
settings := handlers.NewSettingsHandler(uekCache)
protected.GET("/profile", settings.GetProfile)
protected.PUT("/profile", settings.UpdateProfile)
protected.POST("/profile/password", settings.ChangePassword)
@@ -181,6 +185,10 @@ func main() {
protected.GET("/settings", settings.GetSettings)
protected.PUT("/settings", settings.UpdateSettings)
// Usage (personal)
usage := handlers.NewUsageHandler(stores)
protected.GET("/usage", usage.PersonalUsage)
// Personas (replaces /presets)
personas := handlers.NewPersonaHandler(stores)
protected.GET("/presets", personas.ListUserPersonas) // backward compat
@@ -222,19 +230,29 @@ func main() {
teamScoped.DELETE("/providers/:id", teams.DeleteTeamProvider)
teamScoped.GET("/providers/:id/models", teams.ListTeamProviderModels)
// Team audit log (scoped to team members)
// Team audit log (team admins only — RequireTeamAdmin on group)
teamScoped.GET("/audit", teams.ListTeamAuditLog)
teamScoped.GET("/audit/actions", teams.ListTeamAuditActions)
// Team usage (team admins only — usage against team-owned providers)
teamUsage := handlers.NewUsageHandler(stores)
teamScoped.GET("/usage", teamUsage.TeamUsage)
// Team personas
teamPersonas := handlers.NewPersonaHandler(stores)
teamScoped.GET("/presets", teamPersonas.ListTeamPersonas)
teamScoped.POST("/presets", teamPersonas.CreateTeamPersona)
teamScoped.DELETE("/presets/:id", teamPersonas.DeleteTeamPersona)
// Team role overrides
teamRoles := handlers.NewRolesHandler(stores, roleResolver)
teamScoped.GET("/roles", teamRoles.ListTeamRoles)
teamScoped.PUT("/roles/:role", teamRoles.UpdateTeamRole)
teamScoped.DELETE("/roles/:role", teamRoles.DeleteTeamRole)
}
// Public global settings (non-admin users can read safe subset)
adm := handlers.NewAdminHandler(stores, keyResolver)
adm := handlers.NewAdminHandler(stores, keyResolver, uekCache)
protected.GET("/settings/public", adm.PublicSettings)
}
@@ -243,7 +261,7 @@ func main() {
admin.Use(middleware.Auth(cfg))
admin.Use(middleware.RequireAdmin())
{
adm := handlers.NewAdminHandler(stores, keyResolver)
adm := handlers.NewAdminHandler(stores, keyResolver, uekCache)
// User management
admin.GET("/users", adm.ListUsers)
@@ -298,6 +316,22 @@ func main() {
// Audit log
admin.GET("/audit", adm.ListAuditLog)
admin.GET("/audit/actions", adm.ListAuditActions)
// Model Roles
rolesH := handlers.NewRolesHandler(stores, roleResolver)
admin.GET("/roles", rolesH.ListRoles)
admin.GET("/roles/:role", rolesH.GetRole)
admin.PUT("/roles/:role", rolesH.UpdateRole)
admin.POST("/roles/:role/test", rolesH.TestRole)
// Usage & Pricing
usageH := handlers.NewUsageHandler(stores)
admin.GET("/usage", usageH.AdminUsage)
admin.GET("/usage/users/:id", usageH.AdminUserUsage)
admin.GET("/usage/teams/:id", usageH.AdminTeamUsage)
admin.GET("/pricing", usageH.ListPricing)
admin.PUT("/pricing", usageH.UpsertPricing)
admin.DELETE("/pricing/:provider/:model", usageH.DeletePricing)
}
}