feat(db): add oauth_clients table for dynamic client registration
CI / build-and-test (push) Has been cancelled

* Introduced oauth_clients table with fields for client_id, client_name, redirect_uris, and created_at.
* Updated agent_persona_parts, agent_persona_skills, agent_persona_guardrails, agent_persona_traits, and arc_stage_parts tables to use unique constraints instead of primary keys for composite indexes.
This commit is contained in:
Hein
2026-05-07 13:30:30 +02:00
parent fb9606ef2b
commit a993859c62
21 changed files with 1223 additions and 5408 deletions
+2 -2
View File
@@ -100,7 +100,7 @@ func Run(ctx context.Context, configPath string) error {
}
}
authCodes := auth.NewAuthCodeStore()
dynClients := auth.NewDynamicClientStore()
dynClients := auth.NewPostgresClientStore(db.Pool())
activeProjects := session.NewActiveProjects()
logger.Info("ai providers initialised",
@@ -183,7 +183,7 @@ func Run(ctx context.Context, configPath string) error {
}
}
func routes(logger *slog.Logger, cfg *config.Config, info buildinfo.Info, db *store.DB, embeddings *ai.EmbeddingRunner, metadata *ai.MetadataRunner, bgEmbeddings *ai.EmbeddingRunner, bgMetadata *ai.MetadataRunner, keyring *auth.Keyring, oauthRegistry *auth.OAuthRegistry, tokenStore *auth.TokenStore, authCodes *auth.AuthCodeStore, dynClients *auth.DynamicClientStore, activeProjects *session.ActiveProjects) (http.Handler, error) {
func routes(logger *slog.Logger, cfg *config.Config, info buildinfo.Info, db *store.DB, embeddings *ai.EmbeddingRunner, metadata *ai.MetadataRunner, bgEmbeddings *ai.EmbeddingRunner, bgMetadata *ai.MetadataRunner, keyring *auth.Keyring, oauthRegistry *auth.OAuthRegistry, tokenStore *auth.TokenStore, authCodes *auth.AuthCodeStore, dynClients auth.ClientStore, activeProjects *session.ActiveProjects) (http.Handler, error) {
mux := http.NewServeMux()
accessTracker := auth.NewAccessTracker()
oauthEnabled := oauthRegistry != nil
+4 -4
View File
@@ -83,7 +83,7 @@ func oauthMetadataHandler() http.HandlerFunc {
// oauthRegisterHandler serves POST /oauth/register per RFC 7591
// (OAuth 2.0 Dynamic Client Registration).
func oauthRegisterHandler(dynClients *auth.DynamicClientStore, log *slog.Logger) http.HandlerFunc {
func oauthRegisterHandler(dynClients auth.ClientStore, log *slog.Logger) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
w.Header().Set("Allow", http.MethodPost)
@@ -130,7 +130,7 @@ func oauthRegisterHandler(dynClients *auth.DynamicClientStore, log *slog.Logger)
// oauthAuthorizeHandler serves GET and POST /oauth/authorize.
// GET shows an approval page; POST processes the user's approve/deny action.
func oauthAuthorizeHandler(dynClients *auth.DynamicClientStore, authCodes *auth.AuthCodeStore, log *slog.Logger) http.HandlerFunc {
func oauthAuthorizeHandler(dynClients auth.ClientStore, authCodes *auth.AuthCodeStore, log *slog.Logger) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
@@ -144,7 +144,7 @@ func oauthAuthorizeHandler(dynClients *auth.DynamicClientStore, authCodes *auth.
}
}
func handleAuthorizeGET(w http.ResponseWriter, r *http.Request, dynClients *auth.DynamicClientStore) {
func handleAuthorizeGET(w http.ResponseWriter, r *http.Request, dynClients auth.ClientStore) {
q := r.URL.Query()
clientID := q.Get("client_id")
redirectURI := q.Get("redirect_uri")
@@ -178,7 +178,7 @@ func handleAuthorizeGET(w http.ResponseWriter, r *http.Request, dynClients *auth
serveAuthorizePage(w, client.ClientName, clientID, redirectURI, state, codeChallenge, codeChallengeMethod, scope)
}
func handleAuthorizePOST(w http.ResponseWriter, r *http.Request, dynClients *auth.DynamicClientStore, authCodes *auth.AuthCodeStore, log *slog.Logger) {
func handleAuthorizePOST(w http.ResponseWriter, r *http.Request, dynClients auth.ClientStore, authCodes *auth.AuthCodeStore, log *slog.Logger) {
if err := r.ParseForm(); err != nil {
http.Error(w, "invalid form", http.StatusBadRequest)
return
@@ -20,6 +20,7 @@ func resolveSpecModels() []resolveSpecModel {
{schema: "public", entity: "chat_histories", model: generatedmodels.ModelPublicChatHistories{}},
{schema: "public", entity: "embeddings", model: generatedmodels.ModelPublicEmbeddings{}},
{schema: "public", entity: "learnings", model: generatedmodels.ModelPublicLearnings{}},
{schema: "public", entity: "oauth_clients", model: generatedmodels.ModelPublicOauthClients{}},
{schema: "public", entity: "persona_arc", model: generatedmodels.ModelPublicPersonaArc{}},
{schema: "public", entity: "plan_dependencies", model: generatedmodels.ModelPublicPlanDependencies{}},
{schema: "public", entity: "plan_guardrails", model: generatedmodels.ModelPublicPlanGuardrails{}},