Skip to content

feat: update libs#106

Merged
gfyrag merged 1 commit into
mainfrom
feat/bun-tracing
Sep 24, 2025
Merged

feat: update libs#106
gfyrag merged 1 commit into
mainfrom
feat/bun-tracing

Conversation

@gfyrag

@gfyrag gfyrag commented Sep 24, 2025

Copy link
Copy Markdown
Contributor

No description provided.

@coderabbitai

coderabbitai Bot commented Sep 24, 2025

Copy link
Copy Markdown

Walkthrough

Marks the CLI runServe function's args parameter as unused, adjusts OIDC router telemetry to set chi route patterns and span name per-request, and standardizes error descriptions in token revocation paths to use formatted descriptions.

Changes

Cohort / File(s) Summary
Serve command internals
cmd/serve.go
runServe signature changed from func runServe(cmd *cobra.Command, args []string) error to func runServe(cmd *cobra.Command, _ []string) error to mark args as unused; logic unchanged.
OIDC router telemetry hook
pkg/oidc/router.go
Removed unused go.opentelemetry.io/otel/attribute import; replaced direct span attribute manipulation with setting chi.RouteContext(r.Context()).RoutePatterns = []string{r.URL.Path} and trace.SpanFromContext(r.Context()).SetName(r.URL.Path) in the subrouter middleware.
Token revocation error descriptions
pkg/oidc/storage.go
Replaced uses of err.Error() with formatted descriptions via WithDescription("%s", err) across multiple revoke token error paths (Find/Delete access/refresh token and DeleteAccessTokensByRefreshToken), preserving control flow but changing error construction.

Sequence Diagram(s)

sequenceDiagram
    participant C as Client
    participant R as OIDC Router Hook
    participant OT as OpenTelemetry
    participant H as Handler

    C->>R: HTTP request (e.g. /orgs/123)
    R->>R: chi.RouteContext(ctx).RoutePatterns = [r.URL.Path]
    R->>OT: trace.SpanFromContext(ctx).SetName(r.URL.Path)
    R->>H: forward request to handler
    H-->>C: response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • paul-nicolas

Poem

I hop through code and mend the trail,
Spans now wear paths so traces sail.
An underscore hides a quiet name,
Errors dressed with kinder frame.
A rabbit cheers, the traces tame. 🐰

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description Check ⚠️ Warning No pull request description was provided, so there is no summary of the changes and it is not related to the actual modifications in this PR. Please add a pull request description that outlines the purpose of the changes, such as marking unused arguments, updating OTEL span naming in the router, and improving error formatting in the storage package.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title “feat: update libs” is too generic and does not accurately summarize the key changes such as marking an unused parameter, adjusting OTEL span naming for subrouters, or refining error descriptions in the storage layer. Please update the title to briefly describe the main change, for example “refactor: mark unused args, improve OTEL tracing and error descriptions” so that it clearly reflects the core updates in this PR.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/bun-tracing

Comment @coderabbitai help to get the list of available commands and usage tips.

flemzord
flemzord previously approved these changes Sep 24, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
cmd/serve.go (4)

48-76: Do not ship with a hardcoded private key as the default

Embedding a default RSA private key is a severe security risk. Anyone with this source can mint valid tokens if this key is ever used in non‑debug environments.

Apply these changes to only use the built‑in key in debug mode and never as the CLI default:

  • Keep the constant only for debug fallback.
  • Remove it as the default flag value (see Line 104 comment).
  • When no key is provided and debug is enabled, explicitly fall back to this key and log a prominent warning (see Lines 125‑136 comment).

104-104: Remove insecure default for --signing-key

Don’t default the flag to the embedded key. Require an explicit key unless debug mode is on.

-	cmd.Flags().String(SigningKeyFlag, defaultSigningKey, "Signing key")
+	cmd.Flags().String(SigningKeyFlag, "", "Signing key (PEM-encoded RSA private key). Required unless --debug")

125-136: Require signing key; allow explicit debug fallback with warning

Add a safe fallback only in debug and warn loudly. Otherwise, fail fast.

-	signingKey, _ := cmd.Flags().GetString(SigningKeyFlag)
-	if signingKey == "" {
-		return errors.New("signing key must be defined")
-	}
+	signingKey, _ := cmd.Flags().GetString(SigningKeyFlag)
+	if signingKey == "" {
+		if service.IsDebug(cmd) {
+			logging.FromContext(cmd.Context()).Warnf("Using built-in development signing key; DO NOT USE IN PRODUCTION")
+			signingKey = defaultSigningKey
+		} else {
+			return errors.New("signing key must be defined")
+		}
+	}

147-153: Close the config file to avoid a file descriptor leak

The opened file is never closed.

 		configFile, err := os.Open(config)
 		if err != nil {
 			return err
 		}
+		defer configFile.Close()
 		if err := yaml.NewDecoder(configFile).Decode(&o); err != nil {
 			return err
 		}
🧹 Nitpick comments (4)
cmd/serve.go (4)

135-138: Support PKCS#8 keys in addition to PKCS#1

Many deployments use PKCS#8 (“BEGIN PRIVATE KEY”). Fallback to PKCS#8 and ensure the key is RSA.
[Suggest_recommended_refactor]

-	key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
-	if err != nil {
-		return err
-	}
+	var key *rsa.PrivateKey
+	if block.Type == "RSA PRIVATE KEY" {
+		k, err := x509.ParsePKCS1PrivateKey(block.Bytes)
+		if err != nil {
+			return err
+		}
+		key = k
+	} else {
+		k, err := x509.ParsePKCS8PrivateKey(block.Bytes)
+		if err != nil {
+			return errors.Wrap(err, "invalid signing key")
+		}
+		rsaKey, ok := k.(*rsa.PrivateKey)
+		if !ok {
+			return errors.New("signing key must be an RSA private key")
+		}
+		key = rsaKey
+	}

Add the missing import:

// at top of file
import (
    "crypto/rsa"
)

95-99: Enforce no positional args with cobra.NoArgs

Prevents accidental args and improves UX.

 	cmd := &cobra.Command{
 		Use:  "serve",
+		Args: cobra.NoArgs,
 		RunE: runServe,
 	}

106-107: Fix misleading help text for --config

Flag expects a path, not a “name without extension.”

-	cmd.Flags().String(ConfigFlag, "", "Config file name without extension")
+	cmd.Flags().String(ConfigFlag, "", "Config file path (YAML)")

195-203: Build RedirectURL robustly to avoid accidental double slashes

Using simple string formatting can produce “//” if baseUrl ends with “/”.

-				RedirectURL:  fmt.Sprintf("%s/authorize/callback", baseUrl),
+				RedirectURL: func() string {
+					u, err := url.JoinPath(baseUrl, "authorize", "callback")
+					if err != nil {
+						// Fallback to naive concat if join fails
+						return fmt.Sprintf("%s/authorize/callback", baseUrl)
+					}
+					return u
+				}(),

Add import:

import "net/url"
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 017fc5b and 240ea17.

⛔ Files ignored due to path filters (2)
  • go.mod is excluded by !**/*.mod
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (1)
  • cmd/serve.go (1 hunks)
🔇 Additional comments (1)
cmd/serve.go (1)

119-119: Blank identifier for unused args — LGTM

Signature change is correct for Cobra and silences the unused param warning.

@gfyrag gfyrag force-pushed the feat/bun-tracing branch 3 times, most recently from 4cd32d2 to a259427 Compare September 24, 2025 16:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
pkg/oidc/router.go (1)

39-53: Harden against nil RouteContext and make span name more consistent; consider setting http.route

Two tweaks:

  • Guard chi.RouteContext to avoid a rare nil deref.
  • Include the HTTP method in the span name for consistency with common conventions and your client formatter.

Optionally, set http.route to the path to retain useful grouping in backends (be mindful of cardinality if any dynamic segments exist).

Apply this diff inside the handler:

-                    chi.RouteContext(r.Context()).RoutePatterns = []string{"fake"}
-                    trace.SpanFromContext(r.Context()).SetName(r.URL.Path)
+                    if ctx := chi.RouteContext(r.Context()); ctx != nil {
+                        ctx.RoutePatterns = []string{"fake"}
+                    }
+                    span := trace.SpanFromContext(r.Context())
+                    span.SetName(fmt.Sprintf("%s %s", r.Method, r.URL.Path))
+                    // Optional: keep http.route aligned with the chosen naming
+                    // span.SetAttributes(attribute.String("http.route", r.URL.Path))

And add the necessary imports:

// add
import (
    "fmt"
    "go.opentelemetry.io/otel/attribute"
)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4cd32d2 and a259427.

⛔ Files ignored due to path filters (2)
  • go.mod is excluded by !**/*.mod
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (2)
  • cmd/serve.go (1 hunks)
  • pkg/oidc/router.go (1 hunks)
🔇 Additional comments (2)
cmd/serve.go (1)

119-119: Idiomatic unused-parameter marker retained RunE compatibility

Using _ []string keeps the Cobra signature while silencing linters. Looks good.

pkg/oidc/router.go (1)

34-36: Span-name override for subrouter is a sensible workaround

The rationale to avoid otelchi’s default "/*" is sound in this context.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a259427 and 4b2f1dc.

⛔ Files ignored due to path filters (2)
  • go.mod is excluded by !**/*.mod
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (2)
  • cmd/serve.go (1 hunks)
  • pkg/oidc/router.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/serve.go
🔇 Additional comments (2)
pkg/oidc/router.go (2)

37-38: Good placement of middleware around the mounted handler

Wrapping the mounted provider with r.With(...) is the right place to influence how upstream middleware (otelchi) names spans for this subtree.


34-36: Instrument subrouter with otelmux, not manual chi.RouteContext edits

  • Wrap the gorilla/mux router returned by provider.HttpHandler() with otelmux.Middleware("oidc") (import go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux) instead of mutating chi.RouteContext/SpanName manually.
  • Confirm otelchi.Middleware is applied to the parent chi.Router—without it, these overrides have no effect.

Comment thread pkg/oidc/router.go
Comment on lines +51 to +52
chi.RouteContext(r.Context()).RoutePatterns = []string{r.URL.Path}
trace.SpanFromContext(r.Context()).SetName(r.URL.Path)

@coderabbitai coderabbitai Bot Sep 24, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid high-cardinality span names/attributes; remove redundant SetName and normalize the route

Using r.URL.Path for both RoutePatterns and span name can explode span/attribute cardinality and costs. Also, otelchi will likely override your SetName in its deferred block, making it redundant. Normalize to a stable pattern and guard against a missing chi.RouteContext.

Apply this diff:

-                    chi.RouteContext(r.Context()).RoutePatterns = []string{r.URL.Path}
-                    trace.SpanFromContext(r.Context()).SetName(r.URL.Path)
+                    if rc := chi.RouteContext(r.Context()); rc != nil {
+                        // Use a low‑cardinality pattern so metrics/traces aggregate well
+                        rp := normalizeOIDCRoute(r.URL.Path)
+                        rc.RoutePatterns = []string{rp}
+                    }

And add this helper in the same package (adjust/extend as needed):

// normalizeOIDCRoute returns a low‑cardinality route pattern for known OIDC endpoints.
func normalizeOIDCRoute(path string) string {
	switch path {
	case "/.well-known/openid-configuration",
		"/.well-known/jwks.json",
		"/authorize",
		"/token",
		"/userinfo",
		"/introspect",
		"/revoke",
		"/logout",
		AuthorizeCallbackPath:
		return path
	default:
		// Fallback keeps cardinality bounded instead of using the raw path
		return "/*"
	}
}

Operational note: If you truly need full-path span names, prefer setting only the span name (not HTTP route attribute) and ensure paths don’t contain IDs/PII. Otherwise, prefer instrumenting the subrouter directly (see next comment) to get proper patterns.

🤖 Prompt for AI Agents
In pkg/oidc/router.go around lines 51-52, the code sets high-cardinality values
using r.URL.Path for RoutePatterns and span name and doesn't guard against a
missing chi.RouteContext; replace these with a normalized, low-cardinality route
pattern and avoid calling SetName redundantly (otelchi will override it). Update
the logic to first check chi.RouteContext(r.Context()) != nil before setting
RoutePatterns, use a new normalizeOIDCRoute(path string) helper (placed in the
same package) to map known OIDC endpoints to stable patterns and return a
bounded fallback like "/*" for everything else, and remove the explicit
trace.SpanFromContext(...).SetName(r.URL.Path) call so only normalized patterns
are recorded.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, oauth2 path does not contains dynamic part.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gfyrag Thanks for the clarification! You're absolutely right that standard OAuth2/OIDC endpoints are static paths without dynamic segments, so the cardinality concern is much less relevant in this context.

Since you're confident about the path structure, the current approach should work fine for your use case. The only minor consideration that remains is adding a nil check for chi.RouteContext(r.Context()) to be defensive, but if your middleware setup guarantees it's always present, that's fine too.

I appreciate you sharing the domain context - it helps understand why the direct path usage is appropriate here.


✏ Learnings added
Learnt from: gfyrag
PR: formancehq/auth#106
File: pkg/oidc/router.go:51-52
Timestamp: 2025-09-24T17:39:43.652Z
Learning: In the formancehq/auth codebase, OAuth2/OIDC paths are static and do not contain dynamic segments, making direct use of r.URL.Path for span names acceptable without cardinality concerns.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
pkg/oidc/router.go (1)

34-36: Prefer instrumenting the mux subrouter directly (optional)

If feasible, wrap provider.HttpHandler() with otelmux (gorilla/mux) or otelhttp instrumentation rather than faking chi route patterns; this yields correct patterns and cleaner code.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4b2f1dc and 554fdcf.

⛔ Files ignored due to path filters (2)
  • go.mod is excluded by !**/*.mod
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (2)
  • cmd/serve.go (1 hunks)
  • pkg/oidc/router.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/serve.go
🔇 Additional comments (1)
pkg/oidc/router.go (1)

34-52: Prevent panic and avoid high-cardinality spans; normalize route and drop SetName

  • chi.RouteContext(r.Context()) can be nil here → potential panic on Line 51.
  • Using r.URL.Path for RoutePatterns and span name creates high-cardinality telemetry and costs.
  • otelchi will set the span name from HTTP route in its deferred block; explicit SetName is redundant.

Apply:

-					// set a fake route pattern in the route pattern to prevent otelchi middleware
-					// from overriding the span name
+					// Set a low-cardinality route pattern so otelchi derives a stable span name.
 					// The code from otelchi :
 					//   // set span name & http route attribute if route pattern cannot be determined
 					//	 // during span creation
 					//	 if len(routePattern) == 0 {
 					//		 routePattern = chi.RouteContext(r.Context()).RoutePattern()
 					//		 span.SetAttributes(semconv.HTTPRoute(routePattern))
 					//
 					//		 spanName = addPrefixToSpanName(tw.requestMethodInSpanName, r.Method, routePattern)
 					//		 span.SetName(spanName)
 					//	 }
-					chi.RouteContext(r.Context()).RoutePatterns = []string{r.URL.Path}
-					trace.SpanFromContext(r.Context()).SetName(r.URL.Path)
+					if rc := chi.RouteContext(r.Context()); rc != nil {
+						rc.RoutePatterns = []string{normalizeOIDCRoute(r.URL.Path)}
+					}

Note: After removing SetName, the import go.opentelemetry.io/otel/trace will likely be unused; remove it.

Add this helper in the same package:

// normalizeOIDCRoute returns a low‑cardinality route pattern for known OIDC endpoints.
func normalizeOIDCRoute(path string) string {
	switch path {
	case "/.well-known/openid-configuration",
		"/.well-known/jwks.json",
		"/authorize",
		AuthorizeCallbackPath,
		"/token",
		"/userinfo",
		"/introspect",
		"/revoke",
		"/logout":
		return path
	default:
		// Fallback keeps cardinality bounded instead of using the raw path
		return "/*"
	}
}

@gfyrag gfyrag force-pushed the feat/bun-tracing branch 3 times, most recently from 9f30c77 to da1cdf6 Compare September 24, 2025 17:41

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
pkg/oidc/router.go (1)

39-52: Guard against nil chi.RouteContext; avoid redundant SetName

  • Potential NPE: chi.RouteContext(r.Context()) can be nil; add a nil guard.
  • Redundancy: If otelchi is present, setting RoutePatterns should be enough; explicit SetName is unnecessary and may be overridden or duplicate work.
  • Re cardinality: Using r.URL.Path is acceptable here per your note that OAuth2/OIDC paths are static (ack’d).

Apply this diff:

-                    // set a fake route pattern in the route pattern to prevent otelchi middleware
+                    // set a fake route pattern in the route context to prevent otelchi middleware
                     // from overriding the span name
                     // The code from otelchi :
                     //   // set span name & http route attribute if route pattern cannot be determined
                     //	 // during span creation
                     //	 if len(routePattern) == 0 {
                     //		 routePattern = chi.RouteContext(r.Context()).RoutePattern()
                     //		 span.SetAttributes(semconv.HTTPRoute(routePattern))
                     //
                     //		 spanName = addPrefixToSpanName(tw.requestMethodInSpanName, r.Method, routePattern)
                     //		 span.SetName(spanName)
                     //	 }
-                    chi.RouteContext(r.Context()).RoutePatterns = []string{r.URL.Path}
-                    trace.SpanFromContext(r.Context()).SetName(r.URL.Path)
+                    if rc := chi.RouteContext(r.Context()); rc != nil {
+                        rc.RoutePatterns = []string{r.URL.Path}
+                    }
+                    // Let otelchi derive the span name from the route pattern
pkg/oidc/storage.go (1)

326-341: Repeat check for WithDescription calls; consider not leaking internal errors

  • Same API concern applies to these three calls.
  • Consider avoiding raw internal error messages in OIDC error descriptions to prevent leaking internals. Log server-side; return a generic description to clients.

Apply the API fix consistently:

-        return oidc.ErrServerError().WithDescription("%s", err)
+        return oidc.ErrServerError().WithDescriptionf("%s", err)

If you opt to avoid leaking internals:

-        return oidc.ErrServerError().WithDescriptionf("%s", err)
+        // log the error server-side instead; return a generic description to the client
+        return oidc.ErrServerError().WithDescription("internal server error")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between da1cdf6 and 764ba59.

⛔ Files ignored due to path filters (2)
  • go.mod is excluded by !**/*.mod
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (3)
  • cmd/serve.go (1 hunks)
  • pkg/oidc/router.go (1 hunks)
  • pkg/oidc/storage.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/serve.go
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-24T17:39:43.652Z
Learnt from: gfyrag
PR: formancehq/auth#106
File: pkg/oidc/router.go:51-52
Timestamp: 2025-09-24T17:39:43.652Z
Learning: In the formancehq/auth codebase, OAuth2/OIDC paths are static and do not contain dynamic segments, making direct use of r.URL.Path for span names acceptable without cardinality concerns.

Applied to files:

  • pkg/oidc/router.go
🧬 Code graph analysis (1)
pkg/oidc/storage.go (1)
pkg/storage/errors.go (1)
  • IgnoreNotFoundError (11-16)
🔇 Additional comments (2)
pkg/oidc/router.go (1)

34-35: Ack: good context on span naming override

Comment clearly explains the gorilla/mux subrouter case and why a custom span naming approach is needed here.

pkg/oidc/storage.go (1)

312-324: No change needed for WithDescription usage
WithDescription(desc string, args ...any) supports printf-style formatting, so .WithDescription("%s", err) is valid.

@gfyrag gfyrag merged commit 69aae1a into main Sep 24, 2025
6 checks passed
@gfyrag gfyrag deleted the feat/bun-tracing branch September 24, 2025 18:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants