A community based topic aggregation platform built on atproto

feat(oauth): use conventional client_id path for clean brand display

Change OAuth client_id from /oauth/client-metadata.json to
/oauth-client-metadata.json to match atproto's "conventional" pattern.

This causes the PDS OAuth authorization screen to display just
"coves.social" instead of the full URL path, providing a cleaner
user experience.

Per atproto spec, a "conventional" client_id must be:
- https:// protocol
- pathname exactly /oauth-client-metadata.json
- no port or query string

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+5 -4
+2 -1
internal/api/routes/oauth.go
··· 27 27 logoutLimiter := middleware.NewRateLimiter(10, 1*time.Minute) 28 28 29 29 // OAuth metadata endpoints - public, no extra rate limiting (use global limit) 30 - r.Get("/oauth/client-metadata.json", handler.HandleClientMetadata) 30 + // Serve at root /oauth-client-metadata.json so OAuth screens show clean brand domain 31 + r.Get("/oauth-client-metadata.json", handler.HandleClientMetadata) 31 32 r.Get("/.well-known/oauth-protected-resource", handler.HandleProtectedResourceMetadata) 32 33 33 34 // OAuth flow endpoints - stricter rate limiting for authentication attempts
+1 -1
internal/atproto/oauth/client.go
··· 90 90 } else { 91 91 // Production mode: public OAuth client with HTTPS 92 92 // client_id must be the URL of the client metadata document per atproto OAuth spec 93 - clientID := config.PublicURL + "/oauth/client-metadata.json" 93 + clientID := config.PublicURL + "/oauth-client-metadata.json" 94 94 callbackURL := config.PublicURL + "/oauth/callback" 95 95 clientConfig = oauth.NewPublicConfig(clientID, callbackURL, config.Scopes) 96 96 }
+1 -1
internal/atproto/oauth/handlers.go
··· 210 210 } 211 211 212 212 // HandleClientMetadata serves the OAuth client metadata document 213 - // GET /oauth/client-metadata.json 213 + // GET /oauth-client-metadata.json 214 214 func (h *OAuthHandler) HandleClientMetadata(w http.ResponseWriter, r *http.Request) { 215 215 metadata := h.client.ClientMetadata() 216 216
+1 -1
internal/atproto/oauth/handlers_test.go
··· 50 50 51 51 // Validate metadata 52 52 // Per atproto OAuth spec, client_id for public clients is the client metadata URL 53 - assert.Equal(t, "https://coves.social/oauth/client-metadata.json", metadata.ClientID) 53 + assert.Equal(t, "https://coves.social/oauth-client-metadata.json", metadata.ClientID) 54 54 assert.Contains(t, metadata.RedirectURIs, "https://coves.social/oauth/callback") 55 55 assert.Contains(t, metadata.GrantTypes, "authorization_code") 56 56 assert.Contains(t, metadata.GrantTypes, "refresh_token")