Conversation
|
|
@Flo4604 is attempting to deploy a commit to the Unkey Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughThis change introduces a new, operation-based API and backend model for updating API key credits, replacing the previous refill/remaining model. It adds a new handler, OpenAPI schema, SQL queries, and tests for incrementing, decrementing, or setting credits, and updates related constants and route registration. Extensive tests cover success, error, and permission scenarios. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant API_Server
participant Auth
participant DB
participant AuditLog
Client->>API_Server: POST /v2/keys.updateCredits (keyId, operation, value)
API_Server->>Auth: Verify root key & permissions
Auth-->>API_Server: Auth result
API_Server->>DB: Fetch key by keyId
DB-->>API_Server: Key data
API_Server->>DB: Update credits (set/increment/decrement)
DB-->>API_Server: Update result
API_Server->>DB: (If needed) Update refill fields
DB-->>API_Server: Update result
API_Server->>AuditLog: Record update event
API_Server-->>Client: 200 OK (updated credits data)
Suggested labels
Suggested reviewers
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (11)
🧰 Additional context used🧠 Learnings (11)📓 Common learningsgo/pkg/db/queries/key_update_credits_refill.sql (2)go/pkg/db/queries/key_update_credits.sql (1)go/apps/api/routes/v2_keys_update_credits/404_test.go (1)go/apps/api/routes/v2_keys_update_credits/200_test.go (1)go/pkg/db/key_update_credits_refill.sql_generated.go (1)go/apps/api/routes/v2_keys_update_credits/403_test.go (1)go/pkg/db/key_update_credits.sql_generated.go (2)go/apps/api/routes/v2_keys_update_credits/handler.go (2)go/apps/api/routes/v2_keys_update_credits/400_test.go (2)go/apps/api/openapi/openapi.yaml (7)undefined <retrieved_learning> <retrieved_learning> <retrieved_learning> <retrieved_learning> <retrieved_learning> <retrieved_learning> <retrieved_learning> 🧬 Code Graph Analysis (1)go/pkg/db/querier_generated.go (2)
🪛 YAMLlint (1.37.1)go/apps/api/openapi/openapi.yaml[warning] 1018-1018: too few spaces before comment: expected 2 (comments) ⏰ Context from checks skipped due to timeout of 90000ms (19)
🔇 Additional comments (4)
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
Thank you for following the naming conventions for pull request titles! 🙏 |
|
I'm puzzled why vercel doesn't like you... you're in the team |
|
Same here, especially since I just approved the vercel workflow myself 😅 |
There was a problem hiding this comment.
Actionable comments posted: 14
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (18)
go/apps/api/openapi/gen.go(4 hunks)go/apps/api/openapi/openapi.yaml(6 hunks)go/apps/api/routes/register.go(2 hunks)go/apps/api/routes/v2_apis_list_keys/handler.go(1 hunks)go/apps/api/routes/v2_keys_create_key/handler.go(1 hunks)go/apps/api/routes/v2_keys_get_key/handler.go(1 hunks)go/apps/api/routes/v2_keys_update_credits/200_test.go(1 hunks)go/apps/api/routes/v2_keys_update_credits/400_test.go(1 hunks)go/apps/api/routes/v2_keys_update_credits/401_test.go(1 hunks)go/apps/api/routes/v2_keys_update_credits/403_test.go(1 hunks)go/apps/api/routes/v2_keys_update_credits/404_test.go(1 hunks)go/apps/api/routes/v2_keys_update_credits/handler.go(1 hunks)go/internal/services/ratelimit/replay.go(0 hunks)go/pkg/db/key_update_credits.sql_generated.go(1 hunks)go/pkg/db/key_update_credits_refill.sql_generated.go(1 hunks)go/pkg/db/querier_generated.go(1 hunks)go/pkg/db/queries/key_update_credits.sql(1 hunks)go/pkg/db/queries/key_update_credits_refill.sql(1 hunks)
💤 Files with no reviewable changes (1)
- go/internal/services/ratelimit/replay.go
🧰 Additional context used
🧠 Learnings (15)
📓 Common learnings
Learnt from: MichaelUnkey
PR: unkeyed/unkey#2114
File: apps/api/src/routes/v1_keys_updateKey.error.test.ts:0-0
Timestamp: 2024-09-27T15:20:05.475Z
Learning: In the `v1/keys.updateKey` endpoint, the server validates the refill configuration before checking if the key exists. Therefore, tests can assert validation errors without needing to create the key first.
Learnt from: Flo4604
PR: unkeyed/unkey#2955
File: go/apps/api/routes/v2_identities_create_identity/handler.go:162-202
Timestamp: 2025-03-19T09:25:59.751Z
Learning: In the Unkey codebase, input validation for API endpoints is primarily handled through OpenAPI schema validation, which occurs before requests reach the handler code. For example, in the identities.createIdentity endpoint, minimum values for ratelimit duration and limit are defined in the OpenAPI schema rather than duplicating these checks in the handler.
go/pkg/db/queries/key_update_credits_refill.sql (1)
Learnt from: MichaelUnkey
PR: unkeyed/unkey#2114
File: apps/api/src/routes/v1_keys_updateKey.error.test.ts:0-0
Timestamp: 2024-09-27T15:20:05.475Z
Learning: In the `v1/keys.updateKey` endpoint, the server validates the refill configuration before checking if the key exists. Therefore, tests can assert validation errors without needing to create the key first.
go/apps/api/routes/v2_keys_create_key/handler.go (1)
Learnt from: MichaelUnkey
PR: unkeyed/unkey#2114
File: apps/api/src/routes/v1_keys_updateKey.error.test.ts:0-0
Timestamp: 2024-09-27T15:20:05.475Z
Learning: In the `v1/keys.updateKey` endpoint, the server validates the refill configuration before checking if the key exists. Therefore, tests can assert validation errors without needing to create the key first.
go/apps/api/routes/v2_keys_get_key/handler.go (1)
Learnt from: MichaelUnkey
PR: unkeyed/unkey#2114
File: apps/api/src/routes/v1_keys_updateKey.error.test.ts:0-0
Timestamp: 2024-09-27T15:20:05.475Z
Learning: In the `v1/keys.updateKey` endpoint, the server validates the refill configuration before checking if the key exists. Therefore, tests can assert validation errors without needing to create the key first.
go/apps/api/routes/v2_keys_update_credits/401_test.go (2)
Learnt from: MichaelUnkey
PR: unkeyed/unkey#2114
File: apps/api/src/routes/v1_keys_updateKey.error.test.ts:0-0
Timestamp: 2024-09-27T15:20:05.475Z
Learning: In the `v1/keys.updateKey` endpoint, the server validates the refill configuration before checking if the key exists. Therefore, tests can assert validation errors without needing to create the key first.
Learnt from: Flo4604
PR: unkeyed/unkey#2955
File: go/apps/api/routes/v2_identities_create_identity/handler.go:162-202
Timestamp: 2025-03-19T09:25:59.751Z
Learning: In the Unkey codebase, input validation for API endpoints is primarily handled through OpenAPI schema validation, which occurs before requests reach the handler code. For example, in the identities.createIdentity endpoint, minimum values for ratelimit duration and limit are defined in the OpenAPI schema rather than duplicating these checks in the handler.
go/pkg/db/queries/key_update_credits.sql (1)
Learnt from: chronark
PR: unkeyed/unkey#3420
File: go/pkg/hydra/store/gorm/gorm.go:486-498
Timestamp: 2025-07-02T11:51:58.572Z
Learning: The Hydra package (go/pkg/hydra) is planned to be migrated from GORM to sqlc for database operations, which explains why raw SQL queries are acceptable in the current implementation.
go/apps/api/routes/v2_keys_update_credits/200_test.go (1)
Learnt from: MichaelUnkey
PR: unkeyed/unkey#2114
File: apps/api/src/routes/v1_keys_updateKey.error.test.ts:0-0
Timestamp: 2024-09-27T15:20:05.475Z
Learning: In the `v1/keys.updateKey` endpoint, the server validates the refill configuration before checking if the key exists. Therefore, tests can assert validation errors without needing to create the key first.
go/apps/api/routes/v2_keys_update_credits/400_test.go (2)
Learnt from: MichaelUnkey
PR: unkeyed/unkey#2114
File: apps/api/src/routes/v1_keys_updateKey.error.test.ts:0-0
Timestamp: 2024-09-27T15:20:05.475Z
Learning: In the `v1/keys.updateKey` endpoint, the server validates the refill configuration before checking if the key exists. Therefore, tests can assert validation errors without needing to create the key first.
Learnt from: Flo4604
PR: unkeyed/unkey#2955
File: go/apps/api/routes/v2_identities_create_identity/handler.go:162-202
Timestamp: 2025-03-19T09:25:59.751Z
Learning: In the Unkey codebase, input validation for API endpoints is primarily handled through OpenAPI schema validation, which occurs before requests reach the handler code. For example, in the identities.createIdentity endpoint, minimum values for ratelimit duration and limit are defined in the OpenAPI schema rather than duplicating these checks in the handler.
go/apps/api/routes/v2_keys_update_credits/403_test.go (1)
Learnt from: MichaelUnkey
PR: unkeyed/unkey#2114
File: apps/api/src/routes/v1_keys_updateKey.error.test.ts:0-0
Timestamp: 2024-09-27T15:20:05.475Z
Learning: In the `v1/keys.updateKey` endpoint, the server validates the refill configuration before checking if the key exists. Therefore, tests can assert validation errors without needing to create the key first.
go/apps/api/routes/v2_keys_update_credits/404_test.go (1)
Learnt from: MichaelUnkey
PR: unkeyed/unkey#2114
File: apps/api/src/routes/v1_keys_updateKey.error.test.ts:0-0
Timestamp: 2024-09-27T15:20:05.475Z
Learning: In the `v1/keys.updateKey` endpoint, the server validates the refill configuration before checking if the key exists. Therefore, tests can assert validation errors without needing to create the key first.
go/pkg/db/key_update_credits.sql_generated.go (1)
Learnt from: chronark
PR: unkeyed/unkey#3420
File: go/pkg/hydra/store/gorm/gorm.go:486-498
Timestamp: 2025-07-02T11:51:58.572Z
Learning: The Hydra package (go/pkg/hydra) is planned to be migrated from GORM to sqlc for database operations, which explains why raw SQL queries are acceptable in the current implementation.
go/apps/api/routes/v2_keys_update_credits/handler.go (1)
Learnt from: Flo4604
PR: unkeyed/unkey#2955
File: go/apps/api/routes/v2_identities_create_identity/handler.go:162-202
Timestamp: 2025-03-19T09:25:59.751Z
Learning: In the Unkey codebase, input validation for API endpoints is primarily handled through OpenAPI schema validation, which occurs before requests reach the handler code. For example, in the identities.createIdentity endpoint, minimum values for ratelimit duration and limit are defined in the OpenAPI schema rather than duplicating these checks in the handler.
go/pkg/db/key_update_credits_refill.sql_generated.go (1)
Learnt from: chronark
PR: unkeyed/unkey#3420
File: go/pkg/hydra/store/gorm/gorm.go:486-498
Timestamp: 2025-07-02T11:51:58.572Z
Learning: The Hydra package (go/pkg/hydra) is planned to be migrated from GORM to sqlc for database operations, which explains why raw SQL queries are acceptable in the current implementation.
go/apps/api/openapi/gen.go (1)
undefined
<retrieved_learning>
Learnt from: MichaelUnkey
PR: #2114
File: apps/api/src/routes/v1_keys_updateKey.error.test.ts:0-0
Timestamp: 2024-09-27T15:20:05.475Z
Learning: In the v1/keys.updateKey endpoint, the server validates the refill configuration before checking if the key exists. Therefore, tests can assert validation errors without needing to create the key first.
</retrieved_learning>
go/apps/api/openapi/openapi.yaml (4)
undefined
<retrieved_learning>
Learnt from: Flo4604
PR: #3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.669Z
Learning: In the Unkey codebase, OpenAPI 3.1 is used, which allows sibling keys (such as description) alongside $ref in schema objects. Do not flag this as an error in future reviews.
</retrieved_learning>
<retrieved_learning>
Learnt from: chronark
PR: #2693
File: apps/api/src/routes/v1_keys_updateKey.ts:350-368
Timestamp: 2024-11-29T15:15:47.308Z
Learning: In apps/api/src/routes/v1_keys_updateKey.ts, the code intentionally handles externalId and ownerId separately for clarity. The ownerId field will be removed in the future, simplifying the code.
</retrieved_learning>
<retrieved_learning>
Learnt from: MichaelUnkey
PR: #2114
File: apps/api/src/routes/v1_keys_updateKey.error.test.ts:0-0
Timestamp: 2024-09-27T15:20:05.475Z
Learning: In the v1/keys.updateKey endpoint, the server validates the refill configuration before checking if the key exists. Therefore, tests can assert validation errors without needing to create the key first.
</retrieved_learning>
<retrieved_learning>
Learnt from: Flo4604
PR: #2955
File: go/apps/api/routes/v2_identities_create_identity/handler.go:162-202
Timestamp: 2025-03-19T09:25:59.751Z
Learning: In the Unkey codebase, input validation for API endpoints is primarily handled through OpenAPI schema validation, which occurs before requests reach the handler code. For example, in the identities.createIdentity endpoint, minimum values for ratelimit duration and limit are defined in the OpenAPI schema rather than duplicating these checks in the handler.
</retrieved_learning>
🧬 Code Graph Analysis (4)
go/apps/api/routes/v2_apis_list_keys/handler.go (2)
go/apps/api/openapi/gen.go (2)
Daily(20-20)Monthly(21-21)go/pkg/db/models_generated.go (1)
Key(300-324)
go/apps/api/routes/v2_keys_create_key/handler.go (1)
go/apps/api/openapi/gen.go (1)
Monthly(21-21)
go/apps/api/routes/v2_keys_get_key/handler.go (1)
go/apps/api/openapi/gen.go (2)
Daily(20-20)Monthly(21-21)
go/pkg/db/querier_generated.go (2)
go/pkg/db/key_update_credits.sql_generated.go (1)
UpdateKeyCreditsParams(24-28)go/pkg/db/key_update_credits_refill.sql_generated.go (1)
UpdateKeyCreditsRefillParams(17-21)
🪛 YAMLlint (1.37.1)
go/apps/api/openapi/openapi.yaml
[warning] 1018-1018: too few spaces before comment: expected 2
(comments)
🔇 Additional comments (16)
go/apps/api/routes/v2_apis_list_keys/handler.go (1)
382-384: LGTM: Refill interval constant updates are correct.The updates from the old enum constants to the simplified
openapi.Dailyandopenapi.Monthlyconstants are consistent with the broader refactoring and align with the new definitions ingo/apps/api/openapi/gen.go.go/apps/api/routes/v2_keys_create_key/handler.go (1)
292-292: LGTM: Refill interval constant update is correct.The update to use
openapi.Monthlyinstead of the previous enum constant is consistent with the refactoring and aligns with the new constant definitions.go/apps/api/routes/register.go (2)
42-42: LGTM: Import for new handler added correctly.The import for
v2KeysUpdateCreditsfollows the established naming pattern and is placed appropriately with other v2/keys imports.
367-377: LGTM: Route registration is well-structured.The registration for the new
v2/keys.updateCreditsendpoint follows the established pattern with:
- Proper middleware usage (defaultMiddlewares)
- All required dependencies injected (Logger, DB, Keys, Permissions, Auditlogs)
- Logical placement within the v2/keys section
go/apps/api/routes/v2_keys_get_key/handler.go (1)
241-243: LGTM: Refill interval constant updates are correct.The updates to use
openapi.Dailyandopenapi.Monthlyinstead of the previous enum constants are consistent with the refactoring and maintain consistency across route handlers.go/pkg/db/queries/key_update_credits.sql (1)
1-9: LGTM! Solid approach to credit operations with safety measures.The CASE-based approach correctly handles all three operations (set, increment, decrement) and includes proper safeguards to prevent negative credit values during decrement operations.
go/apps/api/routes/v2_keys_update_credits/401_test.go (1)
19-147: Excellent comprehensive authorization test coverage.The test suite properly covers all critical authorization failure scenarios:
- Missing authorization header
- Empty authorization header
- Malformed headers (no Bearer prefix, Bearer only)
- Invalid/nonexistent tokens
The test setup is thorough and the status code expectations are correct (400 for malformed requests, 401 for invalid credentials).
go/pkg/db/querier_generated.go (1)
862-876: Generated interface methods follow established patterns correctly.The new
UpdateKeyCreditsandUpdateKeyCreditsRefillmethods are properly generated and consistent with the existing codebase patterns. Method signatures, documentation, and parameter handling all align with the established conventions.go/pkg/db/key_update_credits_refill.sql_generated.go (1)
1-29: Standard generated code follows established patterns.The generated code for
UpdateKeyCreditsRefillis consistent with the codebase standards. The SQL query, parameter struct, and method implementation all follow the established patterns correctly.go/apps/api/routes/v2_keys_update_credits/404_test.go (1)
35-45: Correct 404 test implementation.The test properly verifies that a non-existent key ID returns a 404 status with an appropriate error message. The setup and assertions are correct for this scenario.
go/pkg/db/key_update_credits.sql_generated.go (1)
15-20: Good implementation of preventing negative creditsThe CASE statement properly handles decrement operations to prevent negative balances by setting to 0 when the result would be negative.
go/apps/api/routes/v2_keys_update_credits/403_test.go (1)
21-193: Comprehensive permission and access control testingExcellent coverage of various authorization scenarios including no permissions, wrong permissions, cross-workspace, and cross-API access. The test properly validates that the endpoint enforces strict permission boundaries.
go/apps/api/routes/v2_keys_update_credits/handler.go (3)
147-149: Verify integer overflow safetyThe conversion from int64 to int32 uses
nolint:gosec. Ensure this is safe by validating the input range.Consider adding validation to ensure the value fits in int32:
if !req.Value.IsNull() && req.Value.IsSpecified() { + if reqVal > math.MaxInt32 || reqVal < math.MinInt32 { + return fault.New("value out of range", + fault.Code(codes.App.Validation.InvalidInput.URN()), + fault.Internal("value exceeds int32 range"), + fault.Public("The provided value is out of the acceptable range."), + ) + } credits = sql.NullInt32{Int32: int32(reqVal), Valid: true} // nolint:gosec }
124-130: Good validation for operation requirementsThe validation properly ensures that increment/decrement operations must include a value, preventing undefined behavior.
151-242: Well-structured transaction handlingThe use of
TxWithResultensures atomic updates for both credits and refill data, with proper error handling and rollback on failure. The audit logging is comprehensive and captures all relevant information.go/apps/api/openapi/gen.go (1)
19-22: LGTM! Well-structured implementation of the new credit update system.The changes introduce a clean, operation-based API for updating credits with:
- Clear operation types (
set,increment,decrement)- Comprehensive documentation explaining edge cases
- Proper use of nullable types for the optional
valuefield- Consistent naming patterns with the rest of the codebase
The transition from the previous
updateRemainingmodel to this more flexibleupdateCreditsapproach provides better control over credit operations.Also applies to: 37-42, 1566-1605, 2243-2244
|
did you add your github account in vercel? I think the email doesn’t match your github and that’s why |
|
whoops |
|
now I did |
What does this PR do?
UpdateCredits endpoint for #3419
Type of change
How should this be tested?
Unit Tests
Checklist
Required
pnpm buildpnpm fmtconsole.logsgit pull origin mainAppreciated
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Tests
Chores