Initial import — snapshot from admin host /srv/gosec/gsc-ops-api
This repo had no version control prior to this commit. The import is a
straight snapshot of the working tree at 2026-05-03; the deployed
binary on fihelvop01 was being rebuilt from this source via `make
build` + scp into place, with no upstream review path.
The snapshot already includes one in-flight fix made on 2026-05-03 to
internal/service/persona.go:GetSelfModel — the handler queried
`source` and `strength` columns plus an `is_active = true` filter on
persona.persona_commitments, none of which exist on that table (its
shape is session-bound commitments with `status`, `commitment_meta`,
etc.). The query returned a 500 every time SynapseHub bootstrapped a
persona's self-model, dropping the IdentityConstraints / Commitments /
ConscienceStandards layer from the assembled prompt. The patched
query reads existing columns only (commitment_text, commitment_type),
filters on `status='active'`, and synthesises Source="learned" /
Strength=1.0 to keep the SelfModel response shape stable for callers.
Verified live: `GET /api/v1/personas/70f7cfd9-.../self-model` now
returns 200 with `{identityConstraints:[],commitments:[],
conscienceStandards:[]}` instead of 500.
Future changes go through PRs against this repo — no more bin-only
deploys.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
225
internal/router/router.go
Normal file
225
internal/router/router.go
Normal file
@@ -0,0 +1,225 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
"github.com/gosec/gsc-ops-api/internal/handler"
|
||||
"github.com/gosec/gsc-ops-api/internal/middleware"
|
||||
)
|
||||
|
||||
// Config holds all handler dependencies for route registration
|
||||
type Config struct {
|
||||
Logger zerolog.Logger
|
||||
APIKeys []string
|
||||
Health *handler.HealthHandler
|
||||
LDAPUsers *handler.LDAPUserHandler
|
||||
LDAPGroups *handler.LDAPGroupHandler
|
||||
LDAPEntities *handler.LDAPEntityHandler
|
||||
DNSZones *handler.DNSZoneHandler
|
||||
DNSRecords *handler.DNSRecordHandler
|
||||
DBTenants *handler.DBTenantHandler
|
||||
DBUsers *handler.DBUserHandler
|
||||
Certs *handler.CertHandler
|
||||
PGP *handler.PGPHandler
|
||||
CardDAV *handler.CardDAVHandler
|
||||
PBX *handler.PBXHandler
|
||||
VoiceAgent *handler.VoiceAgentHandler
|
||||
PersonalAgent *handler.PersonalAgentHandler
|
||||
Persona *handler.PersonaHandler
|
||||
}
|
||||
|
||||
// Setup registers all routes on the Fiber app
|
||||
func Setup(app *fiber.App, cfg *Config) {
|
||||
// Global middleware
|
||||
app.Use(recover.New())
|
||||
app.Use(middleware.RequestID())
|
||||
app.Use(middleware.Logging(cfg.Logger))
|
||||
app.Use(middleware.JWTExtract())
|
||||
|
||||
// Health endpoints (no API key required)
|
||||
app.Get("/health", cfg.Health.Liveness)
|
||||
app.Get("/ready", cfg.Health.Readiness)
|
||||
|
||||
// API v1 routes (API key required)
|
||||
api := app.Group("/api/v1", middleware.APIKey(cfg.APIKeys))
|
||||
|
||||
// LDAP Users
|
||||
ldapUsers := api.Group("/ldap/users")
|
||||
ldapUsers.Get("/", cfg.LDAPUsers.List)
|
||||
ldapUsers.Get("/:uid", cfg.LDAPUsers.Get)
|
||||
ldapUsers.Post("/", cfg.LDAPUsers.Create)
|
||||
ldapUsers.Put("/:uid", cfg.LDAPUsers.Update)
|
||||
ldapUsers.Delete("/:uid", cfg.LDAPUsers.Delete)
|
||||
ldapUsers.Post("/:uid/password", cfg.LDAPUsers.ResetPassword)
|
||||
ldapUsers.Get("/:uid/groups", cfg.LDAPUsers.ListGroups)
|
||||
ldapUsers.Get("/:uid/services", cfg.LDAPUsers.ListServices)
|
||||
ldapUsers.Get("/:uid/services/:domain", cfg.LDAPUsers.GetService)
|
||||
|
||||
// LDAP Groups
|
||||
ldapGroups := api.Group("/ldap/groups")
|
||||
ldapGroups.Get("/", cfg.LDAPGroups.List)
|
||||
ldapGroups.Get("/:cn", cfg.LDAPGroups.Get)
|
||||
ldapGroups.Post("/", cfg.LDAPGroups.Create)
|
||||
ldapGroups.Put("/:cn", cfg.LDAPGroups.Update)
|
||||
ldapGroups.Delete("/:cn", cfg.LDAPGroups.Delete)
|
||||
ldapGroups.Get("/:cn/members", cfg.LDAPGroups.ListMembers)
|
||||
ldapGroups.Post("/:cn/members", cfg.LDAPGroups.AddMembers)
|
||||
ldapGroups.Delete("/:cn/members/:uid", cfg.LDAPGroups.RemoveMember)
|
||||
|
||||
// LDAP Entities (generic CRUD)
|
||||
ldapEntities := api.Group("/ldap/entities")
|
||||
ldapEntities.Get("/", cfg.LDAPEntities.ListTypes)
|
||||
ldapEntities.Get("/:type", cfg.LDAPEntities.List)
|
||||
ldapEntities.Post("/:type", cfg.LDAPEntities.Create)
|
||||
ldapEntities.Get("/:type/:rdn", cfg.LDAPEntities.Get)
|
||||
ldapEntities.Put("/:type/:rdn", cfg.LDAPEntities.Update)
|
||||
ldapEntities.Delete("/:type/:rdn", cfg.LDAPEntities.Delete)
|
||||
|
||||
// DNS Zones
|
||||
dnsZones := api.Group("/dns/zones")
|
||||
dnsZones.Get("/", cfg.DNSZones.List)
|
||||
dnsZones.Get("/:zoneId", cfg.DNSZones.Get)
|
||||
dnsZones.Post("/", cfg.DNSZones.Create)
|
||||
dnsZones.Put("/:zoneId", cfg.DNSZones.Update)
|
||||
dnsZones.Delete("/:zoneId", cfg.DNSZones.Delete)
|
||||
dnsZones.Post("/:zoneId/notify", cfg.DNSZones.Notify)
|
||||
|
||||
// DNS Records
|
||||
dnsZones.Get("/:zoneId/records", cfg.DNSRecords.List)
|
||||
dnsZones.Post("/:zoneId/records", cfg.DNSRecords.Create)
|
||||
dnsZones.Put("/:zoneId/records", cfg.DNSRecords.Replace)
|
||||
dnsZones.Delete("/:zoneId/records", cfg.DNSRecords.Delete)
|
||||
|
||||
// DNS Domains (orchestrated)
|
||||
dnsDomains := api.Group("/dns/domains")
|
||||
dnsDomains.Post("/setup", cfg.DNSRecords.DomainSetup)
|
||||
dnsDomains.Post("/verify", cfg.DNSRecords.DomainVerify)
|
||||
|
||||
// DB Tenants
|
||||
dbTenants := api.Group("/db/tenants")
|
||||
dbTenants.Get("/", cfg.DBTenants.List)
|
||||
dbTenants.Get("/:id", cfg.DBTenants.Get)
|
||||
dbTenants.Post("/", cfg.DBTenants.Create)
|
||||
dbTenants.Put("/:id", cfg.DBTenants.Update)
|
||||
dbTenants.Delete("/:id", cfg.DBTenants.Delete)
|
||||
|
||||
// DB Users
|
||||
dbUsers := api.Group("/db/users")
|
||||
dbUsers.Get("/", cfg.DBUsers.List)
|
||||
dbUsers.Get("/:id", cfg.DBUsers.Get)
|
||||
dbUsers.Post("/", cfg.DBUsers.Create)
|
||||
dbUsers.Put("/:id", cfg.DBUsers.Update)
|
||||
dbUsers.Delete("/:id", cfg.DBUsers.Delete)
|
||||
|
||||
// Certificates
|
||||
certs := api.Group("/certs")
|
||||
certs.Get("/", cfg.Certs.List)
|
||||
certs.Get("/:serialNumber", cfg.Certs.Get)
|
||||
certs.Post("/request", cfg.Certs.Request)
|
||||
certs.Post("/:serialNumber/renew", cfg.Certs.Renew)
|
||||
certs.Post("/:serialNumber/revoke", cfg.Certs.Revoke)
|
||||
|
||||
// PGP Keys
|
||||
pgp := api.Group("/pgp/keys")
|
||||
pgp.Get("/", cfg.PGP.Search)
|
||||
pgp.Get("/:keyId", cfg.PGP.Get)
|
||||
pgp.Post("/", cfg.PGP.Upload)
|
||||
pgp.Delete("/:keyId", cfg.PGP.Delete)
|
||||
|
||||
// PBX
|
||||
if cfg.PBX != nil {
|
||||
pbxTrunks := api.Group("/pbx/trunks")
|
||||
pbxTrunks.Get("/", cfg.PBX.ListTrunks)
|
||||
pbxTrunks.Post("/", cfg.PBX.CreateTrunk)
|
||||
pbxTrunks.Get("/:id", cfg.PBX.GetTrunk)
|
||||
pbxTrunks.Put("/:id", cfg.PBX.UpdateTrunk)
|
||||
pbxTrunks.Delete("/:id", cfg.PBX.DeleteTrunk)
|
||||
pbxTrunks.Post("/:id/activate", cfg.PBX.ActivateTrunk)
|
||||
pbxTrunks.Post("/:id/deactivate", cfg.PBX.DeactivateTrunk)
|
||||
pbxTrunks.Get("/:id/dids", cfg.PBX.ListTrunkDIDs)
|
||||
pbxTrunks.Post("/:id/dids", cfg.PBX.CreateTrunkDID)
|
||||
pbxTrunks.Delete("/:id/dids/:didId", cfg.PBX.DeleteTrunkDID)
|
||||
|
||||
pbxExts := api.Group("/pbx/extensions")
|
||||
pbxExts.Get("/", cfg.PBX.ListExtensions)
|
||||
pbxExts.Post("/", cfg.PBX.CreateExtension)
|
||||
pbxExts.Get("/:id", cfg.PBX.GetExtension)
|
||||
pbxExts.Put("/:id", cfg.PBX.UpdateExtension)
|
||||
pbxExts.Delete("/:id", cfg.PBX.DeleteExtension)
|
||||
|
||||
pbxInbound := api.Group("/pbx/inbound-routes")
|
||||
pbxInbound.Get("/", cfg.PBX.ListInboundRoutes)
|
||||
pbxInbound.Post("/", cfg.PBX.CreateInboundRoute)
|
||||
pbxInbound.Get("/:id", cfg.PBX.GetInboundRoute)
|
||||
pbxInbound.Put("/:id", cfg.PBX.UpdateInboundRoute)
|
||||
pbxInbound.Delete("/:id", cfg.PBX.DeleteInboundRoute)
|
||||
|
||||
pbxOutbound := api.Group("/pbx/outbound-routes")
|
||||
pbxOutbound.Get("/", cfg.PBX.ListOutboundRoutes)
|
||||
pbxOutbound.Post("/", cfg.PBX.CreateOutboundRoute)
|
||||
pbxOutbound.Get("/:id", cfg.PBX.GetOutboundRoute)
|
||||
pbxOutbound.Put("/:id", cfg.PBX.UpdateOutboundRoute)
|
||||
pbxOutbound.Delete("/:id", cfg.PBX.DeleteOutboundRoute)
|
||||
|
||||
api.Get("/pbx/status", cfg.PBX.Status)
|
||||
api.Post("/pbx/reload", cfg.PBX.Reload)
|
||||
}
|
||||
|
||||
// Voice Agents
|
||||
if cfg.VoiceAgent != nil {
|
||||
voiceAgents := api.Group("/voice-agents")
|
||||
voiceAgents.Get("/", cfg.VoiceAgent.ListConfigs)
|
||||
voiceAgents.Post("/", cfg.VoiceAgent.CreateConfig)
|
||||
voiceAgents.Get("/sessions/:sessionId", cfg.VoiceAgent.GetSession)
|
||||
voiceAgents.Get("/:id", cfg.VoiceAgent.GetConfig)
|
||||
voiceAgents.Put("/:id", cfg.VoiceAgent.UpdateConfig)
|
||||
voiceAgents.Delete("/:id", cfg.VoiceAgent.DeleteConfig)
|
||||
voiceAgents.Get("/:id/sessions", cfg.VoiceAgent.ListSessions)
|
||||
}
|
||||
|
||||
// Personal Agents (user agent configs)
|
||||
if cfg.PersonalAgent != nil {
|
||||
agents := api.Group("/agents")
|
||||
agents.Get("/me", cfg.PersonalAgent.GetMyConfig)
|
||||
agents.Put("/me", cfg.PersonalAgent.UpsertMyConfig)
|
||||
agents.Delete("/me", cfg.PersonalAgent.DeleteMyConfig)
|
||||
}
|
||||
|
||||
// Personas
|
||||
if cfg.Persona != nil {
|
||||
personas := api.Group("/personas")
|
||||
personas.Get("/", cfg.Persona.ListPersonas)
|
||||
personas.Post("/", cfg.Persona.CreatePersona)
|
||||
personas.Get("/:id", cfg.Persona.GetPersona)
|
||||
personas.Put("/:id", cfg.Persona.UpdatePersona)
|
||||
personas.Delete("/:id", cfg.Persona.DeletePersona)
|
||||
personas.Get("/:id/self-model", cfg.Persona.GetSelfModel)
|
||||
personas.Get("/:id/experiences", cfg.Persona.GetExperiences)
|
||||
personas.Get("/:id/evaluations/:sessionId", cfg.Persona.GetEvaluations)
|
||||
personas.Get("/:id/moral-pattern/:sessionId", cfg.Persona.GetMoralPattern)
|
||||
}
|
||||
|
||||
// CardDAV
|
||||
if cfg.CardDAV != nil {
|
||||
cardDAVPrincipals := api.Group("/carddav/principals")
|
||||
cardDAVPrincipals.Get("/", cfg.CardDAV.ListPrincipals)
|
||||
cardDAVPrincipals.Get("/:username", cfg.CardDAV.GetPrincipal)
|
||||
cardDAVPrincipals.Post("/", cfg.CardDAV.CreatePrincipal)
|
||||
cardDAVPrincipals.Delete("/:username", cfg.CardDAV.DeletePrincipal)
|
||||
|
||||
cardDAVBooks := api.Group("/carddav/addressbooks")
|
||||
cardDAVBooks.Get("/", cfg.CardDAV.ListAddressBooks)
|
||||
cardDAVBooks.Get("/:id", cfg.CardDAV.GetAddressBook)
|
||||
cardDAVBooks.Post("/", cfg.CardDAV.CreateAddressBook)
|
||||
cardDAVBooks.Put("/:id", cfg.CardDAV.UpdateAddressBook)
|
||||
cardDAVBooks.Delete("/:id", cfg.CardDAV.DeleteAddressBook)
|
||||
|
||||
cardDAVBooks.Get("/:id/contacts", cfg.CardDAV.ListContacts)
|
||||
cardDAVBooks.Get("/:id/contacts/:uri", cfg.CardDAV.GetContact)
|
||||
cardDAVBooks.Post("/:id/contacts", cfg.CardDAV.CreateContact)
|
||||
cardDAVBooks.Put("/:id/contacts/:uri", cfg.CardDAV.UpdateContact)
|
||||
cardDAVBooks.Delete("/:id/contacts/:uri", cfg.CardDAV.DeleteContact)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user