Skip to content

feat: /v2/ratelimit.listOverrides endpoint#3067

Closed
chronark wants to merge 1 commit intomainfrom
v2-ratelimit-list-overrides
Closed

feat: /v2/ratelimit.listOverrides endpoint#3067
chronark wants to merge 1 commit intomainfrom
v2-ratelimit-list-overrides

Conversation

@chronark
Copy link
Collaborator

@chronark chronark commented Apr 2, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a new API endpoint for listing rate limit overrides.
    • Updated and simplified data models to enhance clarity and consistency in managing rate limits.
  • Tests

    • Added extensive tests covering successful requests and various error scenarios (bad requests, unauthorized access, and not-found cases).
  • Chores

    • Updated dependency versions for improved compatibility.
    • Simplified response processing to streamline error handling and maintenance.

@vercel
Copy link

vercel bot commented Apr 2, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
dashboard ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 2, 2025 11:32am
engineering ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 2, 2025 11:32am
play ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 2, 2025 11:32am
www ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 2, 2025 11:32am

@changeset-bot
Copy link

changeset-bot bot commented Apr 2, 2025

⚠️ No Changeset found

Latest commit: b9edd28

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 2, 2025

📝 Walkthrough

Walkthrough

This PR refactors and extends the API for rate limit overrides. It introduces a new constant and type for handling rate limit overrides, updates the OpenAPI specification with new schemas and a POST endpoint (/v2/ratelimit.listOverrides), and standardizes naming by renaming prefixed types. Additionally, the PR adds comprehensive tests for successful requests and various error cases, integrates a new database query with supporting SQL file and generated code, and updates package dependencies while simplifying a client-side method.

Changes

File(s) Change Summary
go/apps/api/openapi/gen.go
go/apps/api/openapi/openapi.json
Added RootKeyScopes constant and RatelimitOverride type; updated and created request/response schemas; aliased and renamed existing V2Ratelimit types; introduced new endpoint schema for /v2/ratelimit.listOverrides.
go/apps/api/routes/register.go
go/apps/api/routes/v2_ratelimit_list_overrides/handler.go
Registered new route for listing overrides; implemented a handler with authentication, request validation, namespace retrieval, permission checks, and response formatting.
go/apps/api/routes/v2_ratelimit_list_overrides/200_test.go
go/apps/api/routes/v2_ratelimit_list_overrides/400_test.go
go/apps/api/routes/v2_ratelimit_list_overrides/401_test.go
go/apps/api/routes/v2_ratelimit_list_overrides/403_test.go
go/apps/api/routes/v2_ratelimit_list_overrides/404_test.go
Added multiple tests covering successful responses, bad requests, unauthorized access, workspace permissions, and not-found scenarios for the new list overrides endpoint.
go/pkg/db/querier_generated.go
go/pkg/db/queries/ratelimit_override_list_by_namespace_id.sql
go/pkg/db/ratelimit_override_list_by_namespace_id.sql_generated.go
Introduced a new DB method and related SQL query to retrieve ratelimit overrides by namespace and workspace.
packages/ratelimit/package.json
packages/ratelimit/src/ratelimit.ts
Updated the dependency version for @unkey/api and simplified the _limit method by removing its promise chain error handling.

Sequence Diagram(s)

sequenceDiagram
  participant C as Client
  participant H as ListOverrides Handler
  participant DB as Database

  C->>H: POST /v2/ratelimit.listOverrides (with auth & request data)
  H->>H: Validate authentication and bind request
  H->>H: Retrieve namespace and validate permissions
  H->>DB: Execute ListRatelimitOverrides query
  DB-->>H: Return overrides data
  H->>C: Respond with 200 OK and overrides list
Loading

Possibly related PRs

Suggested labels

Feature, Dashboard, 🕹️ oss.gg

Suggested reviewers

  • mcstepp
  • perkinsjr
  • MichaelUnkey
  • ogzhanolguncu

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (1.64.8)

Error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2
Failed executing command with error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link
Contributor

github-actions bot commented Apr 2, 2025

Thank you for following the naming conventions for pull request titles! 🙏

@vercel vercel bot temporarily deployed to Preview – play April 2, 2025 11:29 Inactive
@vercel vercel bot temporarily deployed to Preview – engineering April 2, 2025 11:29 Inactive
@vercel vercel bot temporarily deployed to Preview – www April 2, 2025 11:30 Inactive
@vercel vercel bot temporarily deployed to Preview – dashboard April 2, 2025 11:32 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 (9)
go/pkg/db/queries/ratelimit_override_list_by_namespace_id.sql (1)

1-5: SQL query looks good but consider filtering deleted records.

The query correctly retrieves rate limit overrides filtered by workspace_id and namespace_id, using parameterized queries for security. However, you might want to consider:

  1. Adding AND deleted_at_m IS NULL to exclude soft-deleted records
  2. Adding an ORDER BY clause for consistent results
-- name: ListRatelimitOverrides :many
SELECT * FROM ratelimit_overrides
WHERE
    workspace_id = sqlc.arg(workspace_id)
-    AND namespace_id = sqlc.arg(namespace_id);
+    AND namespace_id = sqlc.arg(namespace_id)
+    AND deleted_at_m IS NULL
+ORDER BY created_at_m DESC;
go/apps/api/routes/v2_ratelimit_list_overrides/403_test.go (1)

23-23: Ensure consistent use of UID prefixes across test files.

While this file correctly uses uid.RatelimitNamespacePrefix for namespace IDs, the 404_test.go file uses a custom prefix "test_ns". Consider standardizing on the official prefixes across all test files for consistency.

-namespaceID := uid.New(uid.RatelimitNamespacePrefix)
+namespaceID := uid.New(uid.RatelimitNamespacePrefix)
go/apps/api/routes/v2_ratelimit_list_overrides/404_test.go (1)

23-23: Use standard UID prefix for namespace IDs.

For consistency with other test files (like 403_test.go), use the standard uid.RatelimitNamespacePrefix instead of a custom "test_ns" prefix.

-namespaceID := uid.New("test_ns")
+namespaceID := uid.New(uid.RatelimitNamespacePrefix)
go/apps/api/routes/v2_ratelimit_list_overrides/200_test.go (2)

17-20: Consider a multi-override test scenario.
While this test checks for a single override, testing multiple overrides would provide greater confidence in the list's handling of multiple entries.


82-97: Test empty namespace scenario.
Additionally, consider a scenario where no overrides exist for a namespace to ensure the handler correctly returns an empty list.

go/apps/api/routes/v2_ratelimit_list_overrides/400_test.go (1)

69-83: Add a test for both namespace fields set.
Currently, there's no explicit test confirming how the system behaves if both NamespaceId and NamespaceName are sent together. Consider adding one to validate the expected handling.

go/pkg/db/ratelimit_override_list_by_namespace_id.sql_generated.go (1)

12-17: Consider filtering out deleted overrides.
The query as written retrieves all entries, including those having deleted_at_m set. If you intend to exclude deleted overrides, add a condition to ignore them.

 WHERE
     workspace_id = ?
     AND namespace_id = ?
+    AND deleted_at_m = 0
go/apps/api/routes/v2_ratelimit_list_overrides/handler.go (2)

29-30: Evaluate using GET over POST.
The endpoint retrieves data rather than modifying it, so using the POST method may be semantically less intuitive. Consider using GET for listing resources unless there is a requirement (such as request-body parameters) that strictly demands POST.


119-138: Clarify behavior when both namespace fields are set.
The current logic processes NamespaceId first and then only tries NamespaceName if NamespaceId is nil. If both fields are set, it silently ignores the name. Make your expectation explicit, either by returning an error or choosing which field has priority.

 switch {
 case req.NamespaceId != nil && req.NamespaceName != nil:
-    // Currently unhandled scenario
+    return db.RatelimitNamespace{}, fault.New("both fields provided",
+        fault.WithTag(fault.BAD_REQUEST),
+        fault.WithDesc("ambiguous namespace", "Please specify either namespaceId or namespaceName, but not both."),
+    )
 case req.NamespaceId != nil:
     return db.Query.FindRatelimitNamespaceByID(ctx, svc.DB.RO(), *req.NamespaceId)
 case req.NamespaceName != nil:
     ...
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 21b5de5 and b9edd28.

⛔ Files ignored due to path filters (2)
  • go/gen/proto/ratelimit/v1/service.pb.go is excluded by !**/*.pb.go, !**/gen/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • go/apps/api/openapi/gen.go (5 hunks)
  • go/apps/api/openapi/openapi.json (3 hunks)
  • go/apps/api/routes/register.go (2 hunks)
  • go/apps/api/routes/v2_ratelimit_list_overrides/200_test.go (1 hunks)
  • go/apps/api/routes/v2_ratelimit_list_overrides/400_test.go (1 hunks)
  • go/apps/api/routes/v2_ratelimit_list_overrides/401_test.go (1 hunks)
  • go/apps/api/routes/v2_ratelimit_list_overrides/403_test.go (1 hunks)
  • go/apps/api/routes/v2_ratelimit_list_overrides/404_test.go (1 hunks)
  • go/apps/api/routes/v2_ratelimit_list_overrides/handler.go (1 hunks)
  • go/pkg/db/querier_generated.go (1 hunks)
  • go/pkg/db/queries/ratelimit_override_list_by_namespace_id.sql (1 hunks)
  • go/pkg/db/ratelimit_override_list_by_namespace_id.sql_generated.go (1 hunks)
  • packages/ratelimit/package.json (1 hunks)
  • packages/ratelimit/src/ratelimit.ts (1 hunks)
🧰 Additional context used
🧬 Code Definitions (8)
go/pkg/db/querier_generated.go (3)
go/pkg/db/ratelimit_override_list_by_namespace_id.sql_generated.go (1)
  • ListRatelimitOverridesParams (19-22)
go/apps/api/openapi/gen.go (1)
  • RatelimitOverride (68-83)
go/pkg/db/models_generated.go (1)
  • RatelimitOverride (440-452)
go/apps/api/routes/v2_ratelimit_list_overrides/403_test.go (2)
go/apps/api/routes/v2_ratelimit_list_overrides/handler.go (3)
  • New (29-117)
  • Services (22-27)
  • Request (19-19)
go/apps/api/openapi/gen.go (1)
  • BadRequestError (11-32)
go/apps/api/routes/v2_ratelimit_list_overrides/200_test.go (2)
go/apps/api/routes/v2_ratelimit_list_overrides/handler.go (4)
  • New (29-117)
  • Services (22-27)
  • Request (19-19)
  • Response (20-20)
go/apps/api/routes/register.go (1)
  • Register (15-100)
go/apps/api/routes/v2_ratelimit_list_overrides/handler.go (2)
go/apps/api/openapi/gen.go (3)
  • V2RatelimitListOverridesRequestBody (161-167)
  • V2RatelimitListOverridesResponseBody (170-172)
  • RatelimitOverride (68-83)
go/pkg/db/ratelimit_override_list_by_namespace_id.sql_generated.go (1)
  • ListRatelimitOverridesParams (19-22)
go/pkg/db/ratelimit_override_list_by_namespace_id.sql_generated.go (1)
go/apps/api/openapi/gen.go (1)
  • RatelimitOverride (68-83)
go/apps/api/routes/v2_ratelimit_list_overrides/404_test.go (2)
go/apps/api/routes/v2_ratelimit_list_overrides/handler.go (3)
  • New (29-117)
  • Services (22-27)
  • Request (19-19)
go/apps/api/openapi/gen.go (1)
  • NotFoundError (62-62)
go/apps/api/routes/register.go (2)
go/apps/api/routes/v2_ratelimit_list_overrides/handler.go (2)
  • New (29-117)
  • Services (22-27)
go/apps/api/routes/services.go (1)
  • Services (19-28)
go/apps/api/routes/v2_ratelimit_list_overrides/400_test.go (3)
go/apps/api/routes/v2_ratelimit_list_overrides/handler.go (3)
  • New (29-117)
  • Services (22-27)
  • Request (19-19)
go/apps/api/routes/register.go (1)
  • Register (15-100)
go/apps/api/openapi/gen.go (2)
  • V2RatelimitListOverridesRequestBody (161-167)
  • BadRequestError (11-32)
⏰ Context from checks skipped due to timeout of 90000ms (19)
  • GitHub Check: Test Go API Local / Test (Shard 5/8)
  • GitHub Check: Test Go API Local / Test (Shard 8/8)
  • GitHub Check: Test Go API Local / Test (Shard 6/8)
  • GitHub Check: Test Go API Local / Test (Shard 1/8)
  • GitHub Check: Test Go API Local / Test (Shard 4/8)
  • GitHub Check: Test Packages / Test ./packages/cache
  • GitHub Check: Test Go API Local / Test (Shard 3/8)
  • GitHub Check: Test Packages / Test ./packages/rbac
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Test Packages / Test ./packages/nextjs
  • GitHub Check: Test Packages / Test ./internal/resend
  • GitHub Check: Test Packages / Test ./packages/hono
  • GitHub Check: Test Packages / Test ./packages/api
  • GitHub Check: Test Packages / Test ./internal/keys
  • GitHub Check: Test Packages / Test ./internal/clickhouse
  • GitHub Check: Test Packages / Test ./internal/billing
  • GitHub Check: Test Agent Local / test_agent_local
  • GitHub Check: Build / Build
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (18)
packages/ratelimit/package.json (1)

29-29: Dependency version locked to specific alpha version.

The version of @unkey/api has been changed from a flexible ^2.0.0-alpha.1 to a specific 2.0.0-alpha.5. This is appropriate for alpha releases where breaking changes might occur between minor versions.

go/pkg/db/querier_generated.go (1)

387-393: New query interface method looks good.

The addition of the ListRatelimitOverrides method to the Querier interface follows the established pattern in the codebase. The method signature is correct with appropriate parameters and return types.

go/apps/api/routes/register.go (2)

8-8: Import for new route handler is properly added.

The addition of the import for the v2RatelimitListOverrides package is correct and follows the existing pattern.


77-85: Route registration is well structured.

The registration of the new route for listing rate limit overrides follows the established pattern in the codebase. The route uses the standard middleware stack and provides the necessary services to the handler.

Looking at the handler implementation from the relevant code snippet, it correctly:

  1. Verifies the API key
  2. Checks permissions
  3. Retrieves data using the new database query
  4. Transforms the database results into the API response format
packages/ratelimit/src/ratelimit.ts (1)

171-177: Code simplification looks good.

The change simplifies the _limit method by directly returning the promise from this.unkey.ratelimit.limit without additional promise chain processing. This is a valid improvement since:

  1. Error handling is already present in the public limit method (lines 147-158)
  2. The timeout handling via Promise.race is still intact
  3. The cleanup in the finally block is preserved
go/apps/api/routes/v2_ratelimit_list_overrides/401_test.go (1)

1-40: Well-structured test for unauthorized access.

This test properly validates the 401 Unauthorized response when an invalid token is provided. It includes all necessary components for a comprehensive test:

  • Proper test harness setup
  • Service initialization
  • Request construction with invalid credentials
  • Clear assertions for status code and response body
go/apps/api/routes/v2_ratelimit_list_overrides/403_test.go (1)

1-75: Good security test for workspace isolation.

This test correctly verifies that users from one workspace cannot access rate limit overrides from another workspace. The implementation follows security best practices by masking the existence of resources with a 404 Not Found error rather than revealing unauthorized resources exist.

go/apps/api/routes/v2_ratelimit_list_overrides/404_test.go (1)

18-73: Comprehensive test for not found scenarios.

This test thoroughly validates the API's handling of not found scenarios for both namespace ID and namespace name, which is essential for robust error handling. The test structure is clear and includes appropriate assertions to verify both the status code and error type in the response.

go/apps/api/openapi/openapi.json (5)

210-212: Good refactoring approach using schema reference

The change to reference the common RatelimitOverride schema in V2RatelimitGetOverrideResponseBody improves code reuse and consistency.


213-231: LGTM: Well-structured request schema for listing overrides

The new request schema for listing overrides is well-designed, requiring either namespaceId or namespaceName as expected. This follows the same pattern as other endpoints in the API.


232-244: LGTM: Clear response structure for list operation

The response schema properly defines an array of overrides with the required property constraint, making the API contract clear.


343-379: LGTM: Comprehensive schema definition for RatelimitOverride

The RatelimitOverride schema is well-defined with all necessary properties and constraints:

  • All required fields are specified
  • Clear descriptions for each field
  • Appropriate validation rules (minLength, maxLength, minimum)
  • Good documentation reference for the wildcard rules in identifiers

This standardization will help maintain consistency across the API.


633-715: LGTM: Well-defined endpoint for listing overrides

The new endpoint /v2/ratelimit.listOverrides is properly configured with:

  • Consistent security requirements (rootKey)
  • Appropriate request and response schemas
  • Standard error responses matching other endpoints
  • Clear tagging and operation ID

This maintains consistency with the API's existing patterns.

go/apps/api/openapi/gen.go (5)

67-83: LGTM: Well-structured RatelimitOverride type

The new RatelimitOverride type is well-structured with:

  • Appropriate JSON tags for each field
  • Clear documentation comments
  • Fields aligned with the OpenAPI schema

This type will provide a standardized structure for rate limit overrides across the API.


122-122: Good use of type alias for response model

Using a type alias for V2RatelimitGetOverrideResponseBody that points to RatelimitOverride improves code reuse and consistency.


160-172: LGTM: Clear request and response types for list operation

The new request and response types for listing overrides are well-structured:

  • Request has optional fields with appropriate pointer types
  • Response has a clearly defined slice of overrides
  • Field documentation is clear and consistent

These types align well with the OpenAPI schema definitions.


210-223: Good standardization of naming conventions

Renaming the request body types to remove the "V2" prefix improves naming consistency while maintaining the same functionality. This makes the code more maintainable.


6-8:

Details

❓ Verification inconclusive

Verify usage of the new constant

The new RootKeyScopes constant has been added, but ensure it's used appropriately throughout the codebase.


🏁 Script executed:

#!/bin/bash
# Check for usages of the RootKeyScopes constant
rg "RootKeyScopes" --type go

Length of output: 89


Double-check Usage of RootKeyScopes Constant

  • The constant is defined in go/apps/api/openapi/gen.go (lines 6-8) as:
    const (
        RootKeyScopes = "rootKey.Scopes"
    )
  • A repository-wide search indicates that the constant appears only in its definition file.
  • Please verify whether this is intentional—if RootKeyScopes is meant to be used elsewhere in the codebase (e.g., for API permissions or configuration logic), ensure that those references are added. Otherwise, confirm that its current usage meets the intended design.

@chronark chronark closed this Apr 16, 2025
@imeyer imeyer deleted the v2-ratelimit-list-overrides branch August 6, 2025 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant