Skip to content

feat: /v2/keys.whoami endpoint separate from getKey#3667

Merged
Flo4604 merged 5 commits intomainfrom
07-28-feat__v2_keys.whoami_endpoint_separate_from_getkey
Jul 28, 2025
Merged

feat: /v2/keys.whoami endpoint separate from getKey#3667
Flo4604 merged 5 commits intomainfrom
07-28-feat__v2_keys.whoami_endpoint_separate_from_getkey

Conversation

@chronark
Copy link
Collaborator

@chronark chronark commented Jul 28, 2025

What does this PR do?

This PR removes the oneOf constraint from the V2KeysGetKeyRequestBody.yaml file, making the keyId field required for all requests. Previously, the schema allowed either keyId or key to be required, but now keyId is always required while maintaining the requirement for key in certain cases.

Fixes # (issue)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Chore (refactoring code, technical debt, workflow improvements)
  • Enhancement (small improvements)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How should this be tested?

  • Test that API requests to get a key now require the keyId parameter
  • Verify that the OpenAPI schema validation works correctly with this change
  • Ensure that client SDKs generate the correct type definitions based on the updated schema

Checklist

Required

  • Filled out the "How to test" section in this PR
  • Read Contributing Guide
  • Self-reviewed my own code
  • Commented on my code in hard-to-understand areas
  • Ran pnpm build
  • Ran pnpm fmt
  • Checked for warnings, there are none
  • Removed all console.logs
  • Merged the latest changes from main onto my branch with git pull origin main
  • My changes don't cause any responsiveness issues

Appreciated

  • If a UI change was made: Added a screen recording or screenshots to this PR
  • Updated the Unkey Docs if changes were necessary

Summary by CodeRabbit

  • New Features

    • Introduced a new API endpoint /v2/keys.whoami that allows users to retrieve detailed information about an API key by providing the full key string.
    • The new endpoint returns metadata, permissions, roles, rate limits, credits, and other attributes associated with the API key.
  • Bug Fixes

    • Simplified the existing key retrieval endpoint to require only a key ID, removing support for looking up keys by plaintext key string.
  • Tests

    • Added comprehensive tests for the new /v2/keys.whoami endpoint, covering successful responses, bad requests, unauthorized access, forbidden access, and not found scenarios.
    • Updated and streamlined tests for the existing key retrieval endpoint to reflect the new input requirements.
  • Documentation

    • Updated API documentation to reflect the new endpoint and revised request/response schemas for key retrieval.

@changeset-bot
Copy link

changeset-bot bot commented Jul 28, 2025

⚠️ No Changeset found

Latest commit: fae522e

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

@vercel
Copy link

vercel bot commented Jul 28, 2025

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

2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
dashboard ⬜️ Ignored (Inspect) Visit Preview Jul 28, 2025 1:28pm
engineering ⬜️ Ignored (Inspect) Visit Preview Jul 28, 2025 1:28pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 28, 2025

📝 Walkthrough

Walkthrough

This change removes support for retrieving API keys by their plaintext value from the existing /v2/keys.get_key endpoint, making it accept only keyId. It introduces a new endpoint /v2/keys.whoami that allows key lookup by the full key string, with new OpenAPI schemas, handler implementation, and comprehensive tests for the new route.

Changes

Cohort / File(s) Change Summary
OpenAPI: Remove key-by-plaintext from get_key, add whoami endpoint
go/apps/api/openapi/spec/paths/v2/keys/getKey/V2KeysGetKeyRequestBody.yaml, go/apps/api/openapi/openapi-generated.yaml, go/apps/api/openapi/openapi-split.yaml, go/apps/api/openapi/spec/paths/v2/keys/whoami/V2KeysWhoamiRequestBody.yaml, go/apps/api/openapi/spec/paths/v2/keys/whoami/V2KeysWhoamiResponseBody.yaml, go/apps/api/openapi/spec/paths/v2/keys/whoami/index.yaml
Removes the key property and oneOf constraint from the V2KeysGetKeyRequestBody schema, making keyId required. Adds new OpenAPI schemas and path for /v2/keys.whoami, including request and response bodies, endpoint documentation, and security requirements.
Go OpenAPI type generation
go/apps/api/openapi/gen.go
Removes the union-based struct and logic for V2KeysGetKeyRequestBody, making it a simple struct with a required KeyId string. Adds new types for the whoami endpoint request/response.
API route registration
go/apps/api/routes/register.go
Imports and registers the new /v2/keys.whoami route handler with the server, wiring it up with dependencies.
v2_keys_get_key handler and tests
go/apps/api/routes/v2_keys_get_key/handler.go, go/apps/api/routes/v2_keys_get_key/200_test.go, go/apps/api/routes/v2_keys_get_key/400_test.go, go/apps/api/routes/v2_keys_get_key/401_test.go, go/apps/api/routes/v2_keys_get_key/403_test.go, go/apps/api/routes/v2_keys_get_key/404_test.go, go/apps/api/routes/v2_keys_get_key/412_test.go
Removes all logic and tests related to retrieving keys by plaintext value, making all requests require a KeyId. Refactors tests and handler to use non-pointer KeyId fields. Deletes test cases for key-by-plaintext and for scenarios where both key and keyId were provided or missing.
New v2_keys_whoami handler and tests
go/apps/api/routes/v2_keys_whoami/handler.go, go/apps/api/routes/v2_keys_whoami/200_test.go, go/apps/api/routes/v2_keys_whoami/400_test.go, go/apps/api/routes/v2_keys_whoami/401_test.go, go/apps/api/routes/v2_keys_whoami/404_test.go
Adds a new handler for /v2/keys.whoami that looks up keys by their plaintext value, with all supporting logic for authentication, permissions, metadata, and error handling. Introduces comprehensive tests for success, bad request, unauthorized, not found, and forbidden scenarios.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API_Server
    participant DB
    participant Vault

    Client->>API_Server: POST /v2/keys.whoami { key }
    API_Server->>DB: Find key by hash(key)
    alt Key not found or forbidden
        API_Server-->>Client: 404 Not Found / 403 Forbidden
    else Key found
        API_Server->>Vault: (if encrypted) Decrypt key
        API_Server->>DB: Fetch identity, permissions, ratelimits, etc.
        API_Server-->>Client: 200 OK { key metadata, permissions, etc. }
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Suggested labels

🕹️ oss.gg, :joystick: 300 points

Suggested reviewers

  • perkinsjr
  • mcstepp
  • MichaelUnkey
  • ogzhanolguncu
  • chronark

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 07-28-feat__v2_keys.whoami_endpoint_separate_from_getkey

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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need 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)

  • @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 generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @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.

Copy link
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions
Copy link
Contributor

github-actions bot commented Jul 28, 2025

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

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: 7

🔭 Outside diff range comments (1)
go/apps/api/openapi/spec/paths/v2/keys/getKey/V2KeysGetKeyRequestBody.yaml (1)

42-46: Remove outdated examples referencing the key field.

The examples still reference the key field (lines 42-46 and others) which was removed from the schema. This inconsistency could confuse developers trying to use the API.

-  supportKeyLookup:
-    summary: Support lookup by actual key string
-    description: Look up key details when provided the actual key string (useful for support scenarios)
-    value:
-      key: sk_1234abcdef5678
-      decrypt: false

Similar cleanup should be applied to other examples that reference the removed key field.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 59ad879 and 1b06856.

📒 Files selected for processing (21)
  • go/apps/api/openapi/gen.go (3 hunks)
  • go/apps/api/openapi/openapi-generated.yaml (4 hunks)
  • go/apps/api/openapi/openapi-split.yaml (1 hunks)
  • go/apps/api/openapi/spec/paths/v2/keys/getKey/V2KeysGetKeyRequestBody.yaml (1 hunks)
  • go/apps/api/openapi/spec/paths/v2/keys/whoami/V2KeysWhoamiRequestBody.yaml (1 hunks)
  • go/apps/api/openapi/spec/paths/v2/keys/whoami/V2KeysWhoamiResponseBody.yaml (1 hunks)
  • go/apps/api/openapi/spec/paths/v2/keys/whoami/index.yaml (1 hunks)
  • go/apps/api/routes/register.go (2 hunks)
  • go/apps/api/routes/v2_keys_get_key/200_test.go (9 hunks)
  • go/apps/api/routes/v2_keys_get_key/400_test.go (1 hunks)
  • go/apps/api/routes/v2_keys_get_key/401_test.go (1 hunks)
  • go/apps/api/routes/v2_keys_get_key/403_test.go (1 hunks)
  • go/apps/api/routes/v2_keys_get_key/404_test.go (1 hunks)
  • go/apps/api/routes/v2_keys_get_key/412_test.go (1 hunks)
  • go/apps/api/routes/v2_keys_get_key/handler.go (2 hunks)
  • go/apps/api/routes/v2_keys_whoami/200_test.go (1 hunks)
  • go/apps/api/routes/v2_keys_whoami/400_test.go (1 hunks)
  • go/apps/api/routes/v2_keys_whoami/401_test.go (1 hunks)
  • go/apps/api/routes/v2_keys_whoami/403_test.go (1 hunks)
  • go/apps/api/routes/v2_keys_whoami/404_test.go (1 hunks)
  • go/apps/api/routes/v2_keys_whoami/handler.go (1 hunks)
🧰 Additional context used
🧠 Learnings (18)
📓 Common learnings
Learnt from: chronark
PR: unkeyed/unkey#3617
File: go/apps/api/openapi/openapi.yaml:3309-3312
Timestamp: 2025-07-16T17:51:57.297Z
Learning: In the Unkey API OpenAPI schema, the permissions query regex for the verifyKey endpoint intentionally allows all whitespace characters (including tabs and newlines) via `\s`. Do not flag this as an error in future reviews.
Learnt from: Flo4604
PR: unkeyed/unkey#3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.699Z
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.
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.
Learnt from: chronark
PR: unkeyed/unkey#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.
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: chronark
PR: unkeyed/unkey#3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.
go/apps/api/routes/v2_keys_get_key/403_test.go (1)

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.

go/apps/api/routes/v2_keys_get_key/404_test.go (2)

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.

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.

go/apps/api/routes/v2_keys_get_key/200_test.go (2)

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.

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.

go/apps/api/openapi/spec/paths/v2/keys/getKey/V2KeysGetKeyRequestBody.yaml (8)

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.

Learnt from: Flo4604
PR: #3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.699Z
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.

Learnt from: chronark
PR: #3617
File: go/apps/api/openapi/openapi.yaml:3309-3312
Timestamp: 2025-07-16T17:51:57.297Z
Learning: In the Unkey API OpenAPI schema, the permissions query regex for the verifyKey endpoint intentionally allows all whitespace characters (including tabs and newlines) via \s. Do not flag this as an error in future reviews.

Learnt from: Flo4604
PR: #3151
File: go/apps/api/openapi/gen.go:221-233
Timestamp: 2025-04-18T20:01:33.812Z
Learning: For destructive operations like deletion in the Unkey API, oneOf validation is preferred over anyOf to enforce explicit targeting and prevent ambiguity.

Learnt from: Flo4604
PR: #3151
File: go/apps/api/openapi/gen.go:221-233
Timestamp: 2025-04-18T20:01:33.812Z
Learning: For identity deletion operations in the Unkey API, identityId takes precedence over externalId when both are provided in the request body.

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.

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.

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.

go/apps/api/openapi/spec/paths/v2/keys/whoami/V2KeysWhoamiRequestBody.yaml (3)

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.

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.

Learnt from: Flo4604
PR: #3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.699Z
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.

go/apps/api/routes/v2_keys_get_key/401_test.go (2)

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.

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.

go/apps/api/routes/v2_keys_get_key/400_test.go (2)

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.

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.

go/apps/api/routes/v2_keys_whoami/400_test.go (3)

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.

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.

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.

go/apps/api/openapi/spec/paths/v2/keys/whoami/V2KeysWhoamiResponseBody.yaml (2)

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.

Learnt from: Flo4604
PR: #3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.699Z
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.

go/apps/api/routes/v2_keys_get_key/handler.go (3)

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.

Learnt from: chronark
PR: #3560
File: go/deploy/metald/internal/database/repository.go:0-0
Timestamp: 2025-07-15T14:59:30.212Z
Learning: go/deploy/metald cannot currently import helpers from go/pkg/db because it is not yet part of the main Go module; avoid suggesting such imports until the modules are unified.

Learnt from: Flo4604
PR: #3606
File: go/pkg/prometheus/metrics/database.go:29-30
Timestamp: 2025-07-16T10:06:35.397Z
Learning: In Go packages, variables defined in one file within a package (like latencyBuckets and constLabels in go/pkg/prometheus/metrics/http.go) are accessible from other files in the same package without requiring imports. This is a common pattern for sharing configuration across multiple files within a package.

go/apps/api/openapi/spec/paths/v2/keys/whoami/index.yaml (1)

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.

go/apps/api/routes/v2_keys_whoami/401_test.go (3)

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.

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.

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.

go/apps/api/routes/v2_keys_whoami/handler.go (1)

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.

go/apps/api/routes/v2_keys_whoami/403_test.go (3)

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.

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.

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:468-581
Timestamp: 2025-07-15T14:47:20.490Z
Learning: In the Unkey codebase, role and permission names are validated at the OpenAPI schema layer with strict regex patterns: role names must match "^[a-zA-Z][a-zA-Z0-9_-]*$" (start with letter, followed by letters/numbers/underscores/hyphens) and permission names must match "^[a-zA-Z0-9_]+$" (letters, numbers, underscores only). This validation occurs during zen.BindBody call before handlers run, preventing malicious or improperly formatted names from reaching auto-creation logic.

go/apps/api/openapi/openapi-generated.yaml (5)

Learnt from: Flo4604
PR: #3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.699Z
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.

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.

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.

Learnt from: chronark
PR: #3617
File: go/apps/api/openapi/openapi.yaml:3309-3312
Timestamp: 2025-07-16T17:51:57.297Z
Learning: In the Unkey API OpenAPI schema, the permissions query regex for the verifyKey endpoint intentionally allows all whitespace characters (including tabs and newlines) via \s. Do not flag this as an error in future reviews.

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.

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

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.

Learnt from: Flo4604
PR: #3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.699Z
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.

go/apps/api/routes/v2_keys_whoami/200_test.go (3)

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.

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.

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.

🧬 Code Graph Analysis (2)
go/apps/api/routes/register.go (1)
go/apps/api/routes/v2_keys_whoami/handler.go (1)
  • Handler (28-35)
go/apps/api/openapi/gen.go (2)
go/pkg/db/models_generated.go (1)
  • Key (666-690)
go/pkg/codes/unkey_data.go (1)
  • Data (87-128)
🪛 Gitleaks (8.27.2)
go/apps/api/openapi/spec/paths/v2/keys/whoami/V2KeysWhoamiRequestBody.yaml

20-20: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

go/apps/api/openapi/spec/paths/v2/keys/whoami/V2KeysWhoamiResponseBody.yaml

56-56: Found a Stripe Access Token, posing a risk to payment processing services and sensitive financial data.

(stripe-access-token)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Test Go API Local / Test
  • GitHub Check: Test Agent Local / test_agent_local
  • GitHub Check: Build / Build
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Test Packages / Test
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (35)
go/apps/api/routes/v2_keys_get_key/403_test.go (1)

125-125: LGTM! Correct alignment with simplified request schema.

The change from pointer to direct string value for KeyId correctly reflects the API schema simplification where keyId is now the only required field in the request body.

go/apps/api/openapi/openapi-split.yaml (1)

151-152: LGTM! Proper addition of the new whoami endpoint.

The new /v2/keys.whoami endpoint is correctly added to the OpenAPI specification, following the established patterns and properly positioned within the keys section.

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

39-39: LGTM! Consistent with API schema simplification.

The change from pointer to direct string for KeyId is correct and aligns with the removal of the oneOf constraint from the request schema.

go/apps/api/routes/v2_keys_get_key/401_test.go (1)

29-29: LGTM! Proper adaptation to simplified request structure.

The change from pointer to direct string for KeyId correctly reflects the updated API schema while maintaining comprehensive unauthorized access test coverage.

go/apps/api/routes/v2_keys_get_key/412_test.go (1)

53-53: LGTM! Maintains test integrity with updated request structure.

The change from pointer to direct string for KeyId is correct and preserves the precondition failure test scenario while adapting to the simplified API schema.

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

49-49: LGTM!

The import is correctly placed with other key-related route imports and follows the established naming convention.


416-426: LGTM!

The route registration follows the established pattern perfectly. The handler is instantiated with the same dependencies as other key handlers (Logger, DB, Keys, Auditlogs, Vault) and uses the default middleware stack consistently.

go/apps/api/routes/v2_keys_get_key/200_test.go (1)

100-100: LGTM!

The removal of pointer wrappers from KeyId field assignments correctly reflects the schema simplification. The changes are consistent across all test cases and align with the removal of the oneOf constraint from the OpenAPI schema.

Also applies to: 112-112, 176-176, 200-200, 220-220, 244-244, 280-280, 327-327, 369-369

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

38-38: LGTM!

The change from pointer wrapper to direct string assignment is consistent with the schema simplification. The remaining test adequately covers the validation of empty keyId strings.

go/apps/api/openapi/spec/paths/v2/keys/getKey/V2KeysGetKeyRequestBody.yaml (1)

26-27: LGTM!

The schema simplification correctly removes the oneOf constraint and makes keyId the only required field. This provides a cleaner, more focused API for key retrieval by ID.

go/apps/api/openapi/spec/paths/v2/keys/whoami/V2KeysWhoamiRequestBody.yaml (1)

1-21: LGTM!

The new request body schema is well-designed with:

  • Appropriate validation constraints (minLength: 1, maxLength: 512)
  • Excellent security warnings about not logging/caching API keys
  • Clear documentation about providing the complete key string
  • Proper example usage

The static analysis warning about the example key is a false positive - it's just documentation.

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

15-46: LGTM! Well-structured test for key not found scenario.

The test correctly validates the 404 Not Found response when a nonexistent key is requested. The use of uid.New("api") to generate a valid-looking but nonexistent key is appropriate, and the assertion on the error message content ensures proper error handling.

go/apps/api/openapi/spec/paths/v2/keys/whoami/V2KeysWhoamiResponseBody.yaml (2)

1-9: LGTM! Well-structured response schema with proper references.

The schema correctly defines the response structure with required meta and data properties, using appropriate references to common schemas.


10-122: LGTM! Comprehensive examples covering various key scenarios.

The examples effectively demonstrate different use cases: dashboard keys, API playground with decryption, keys with identity, and expired keys. These examples will help developers understand the API response structure.

Note: The static analysis tool flagged line 56 as containing a Stripe token, but this is a false positive - it's just an example key string in the documentation.

go/apps/api/routes/v2_keys_whoami/401_test.go (1)

14-89: LGTM! Comprehensive authorization testing with appropriate status code distinctions.

The test suite correctly covers various unauthorized access scenarios:

  • Missing/empty authorization headers → 400 (Bad Request)
  • Malformed authorization headers → 400 (Bad Request)
  • Nonexistent root key → 401 (Unauthorized)

The distinction between 400 and 401 status codes is appropriate: malformed requests return 400, while valid format but invalid credentials return 401.

go/apps/api/routes/v2_keys_whoami/403_test.go (2)

20-126: LGTM! Comprehensive test setup for permission scenarios.

The test setup correctly creates multiple APIs, keyrings, and workspaces to test various access control scenarios. The complex setup is necessary and appropriate for testing cross-workspace and cross-API security boundaries.


127-186: LGTM! Thorough permission validation testing with correct status code expectations.

The test suite correctly validates different permission scenarios:

  • No permissions → 403 Forbidden
  • Wrong permissions → 403 Forbidden
  • Cross-workspace access → 404 Not Found (doesn't reveal existence)
  • Cross-API access → 403 Forbidden

The distinction between 403 and 404 responses is security-conscious, preventing information leakage across workspace boundaries.

go/apps/api/routes/v2_keys_get_key/handler.go (2)

62-65: LGTM: Clean simplification of key lookup logic.

The removal of the conditional logic for handling both keyId and key parameters simplifies the handler significantly. Setting the hash parameter to an invalid empty string is appropriate since this endpoint now only handles key retrieval by ID.


170-170: LGTM: Simplified decryption condition.

The decryption logic now correctly focuses only on whether the key is encrypted and has a valid encryption key ID, removing the previous dependency on whether a plaintext key was provided in the request. This aligns well with the endpoint's new single-purpose design.

go/apps/api/openapi/spec/paths/v2/keys/whoami/index.yaml (1)

1-62: LGTM: Well-designed OpenAPI specification for the new whoami endpoint.

This specification demonstrates excellent API design practices:

  • Security-conscious: Uses POST method to keep the sensitive key string in the request body rather than URL parameters
  • Comprehensive documentation: Clear description of required permissions and functionality
  • Complete error handling: Covers all standard HTTP error scenarios (400, 401, 403, 404, 500)
  • Consistent with project patterns: Follows the established naming conventions and schema reference patterns used throughout the Unkey API

The separation of this functionality into a dedicated endpoint aligns well with the PR objective to distinguish between key retrieval by ID vs. by key string.

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

1081-1097: LGTM: V2KeysGetKeyRequestBody correctly simplified

The struct has been appropriately simplified by removing the union-based design and making KeyId a required field. This aligns with the OpenAPI schema change that removed the oneOf constraint and the optional key property.


1540-1554: LGTM: Well-designed whoami request/response types

The new V2KeysWhoamiRequestBody and V2KeysWhoamiResponseBody structs are well-designed:

  • Clear separation of concerns: whoami takes the full key string while getKey uses keyId
  • Appropriate security warnings in the documentation about key handling
  • Consistent reuse of KeyResponseData type for the response
  • Field documentation clearly explains the purpose and usage

2198-2199: LGTM: Consistent alias pattern

The WhoamiJSONRequestBody alias follows the established pattern used throughout the file for other JSON request body types.

go/apps/api/routes/v2_keys_whoami/handler.go (10)

28-46: LGTM!

The handler struct and route methods are correctly implemented.


47-60: LGTM!

Authentication and request validation are properly implemented.


61-101: LGTM!

The key lookup logic is secure and properly validated. Good use of SHA256 hashing and comprehensive error handling.


102-118: LGTM!

Permission checks are correctly implemented with appropriate RBAC rules.


119-147: LGTM!

Response construction correctly handles all basic key fields with proper null handling.


148-168: LGTM!

Credits and refill logic correctly implements daily and monthly refill intervals.


170-221: LGTM!

Identity handling is comprehensive with proper error handling and metadata unmarshaling.


223-242: LGTM!

Ratelimits retrieval and response formatting are correctly implemented.


244-276: LGTM!

Metadata unmarshaling, permissions, and roles retrieval are properly implemented.


277-283: LGTM!

Response formatting correctly follows the API schema structure.

go/apps/api/routes/v2_keys_whoami/200_test.go (2)

1-22: LGTM!

Test imports are appropriate for integration testing.


110-356: LGTM!

Comprehensive test coverage with well-structured test cases covering all major functionality including metadata, expiration, credits, permissions, roles, ratelimits, and disabled keys.

@Flo4604
Copy link
Member

Flo4604 commented Jul 28, 2025

just those minor comments and what rabbit said

Copy link
Collaborator Author

:ty:

Copy link
Member

Flo4604 commented Jul 28, 2025

at some point I want to add a single query that selects all the data we need so we can save ourselves multiple queries but thats an optimization for later

Copy link
Collaborator Author

in before you recreate the drizzle monster query

@graphite-app
Copy link

graphite-app bot commented Jul 28, 2025

Photo gif. A hand giving a thumbs-up appears in front of a photo of Harrison Ford. (Added via Giphy)

@graphite-app
Copy link

graphite-app bot commented Jul 28, 2025

Graphite Automations

"Post a GIF when PR approved" took an action on this PR • (07/28/25)

1 gif was posted to this PR based on Andreas Thomas's automation.

@Flo4604 Flo4604 enabled auto-merge July 28, 2025 11:00
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: 3

♻️ Duplicate comments (3)
go/apps/api/openapi/openapi-generated.yaml (2)

1459-1467: Still missing a regex that enforces key format
Same feedback as in the previous review – consider adding a pattern such as ^sk_[A-Za-z0-9]{32,}$ to catch obvious typos before the handler runs.


5073-5121: operationId too generic & summary misleading

  1. operationId: whoami is likely to collide with other future endpoints; rename to something unique like keysWhoami.
  2. The summary says “Get API key by hash”, yet the request body expects the full key string. Update to reflect the actual behaviour.
go/apps/api/routes/v2_keys_whoami/handler.go (1)

27-27: Fix incorrect endpoint documentation.

The comment incorrectly references "v2 keys.getKey endpoint" but this handler is for the "v2 keys.whoami endpoint".

-// Handler implements zen.Route interface for the v2 keys.getKey endpoint
+// Handler implements zen.Route interface for the v2 keys.whoami endpoint
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1b06856 and f83db15.

📒 Files selected for processing (6)
  • go/apps/api/openapi/openapi-generated.yaml (4 hunks)
  • go/apps/api/openapi/spec/paths/v2/keys/whoami/index.yaml (1 hunks)
  • go/apps/api/routes/v2_keys_get_key/handler.go (2 hunks)
  • go/apps/api/routes/v2_keys_whoami/200_test.go (1 hunks)
  • go/apps/api/routes/v2_keys_whoami/404_test.go (1 hunks)
  • go/apps/api/routes/v2_keys_whoami/handler.go (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: Flo4604
PR: unkeyed/unkey#3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.699Z
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.
Learnt from: chronark
PR: unkeyed/unkey#3617
File: go/apps/api/openapi/openapi.yaml:3309-3312
Timestamp: 2025-07-16T17:51:57.297Z
Learning: In the Unkey API OpenAPI schema, the permissions query regex for the verifyKey endpoint intentionally allows all whitespace characters (including tabs and newlines) via `\s`. Do not flag this as an error in future reviews.
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.
Learnt from: chronark
PR: unkeyed/unkey#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.
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: chronark
PR: unkeyed/unkey#3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.
go/apps/api/openapi/spec/paths/v2/keys/whoami/index.yaml (3)

Learnt from: chronark
PR: #3617
File: go/apps/api/openapi/openapi.yaml:3309-3312
Timestamp: 2025-07-16T17:51:57.297Z
Learning: In the Unkey API OpenAPI schema, the permissions query regex for the verifyKey endpoint intentionally allows all whitespace characters (including tabs and newlines) via \s. Do not flag this as an error in future reviews.

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.

Learnt from: Flo4604
PR: #3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.699Z
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.

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

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.

go/apps/api/routes/v2_keys_get_key/handler.go (4)

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.

Learnt from: chronark
PR: #3560
File: go/deploy/metald/internal/database/repository.go:0-0
Timestamp: 2025-07-15T14:59:30.212Z
Learning: go/deploy/metald cannot currently import helpers from go/pkg/db because it is not yet part of the main Go module; avoid suggesting such imports until the modules are unified.

Learnt from: Flo4604
PR: #3606
File: go/pkg/prometheus/metrics/database.go:29-30
Timestamp: 2025-07-16T10:06:35.397Z
Learning: In Go packages, variables defined in one file within a package (like latencyBuckets and constLabels in go/pkg/prometheus/metrics/http.go) are accessible from other files in the same package without requiring imports. This is a common pattern for sharing configuration across multiple files within a package.

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.

go/apps/api/routes/v2_keys_whoami/200_test.go (12)

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.

Learnt from: chronark
PR: #3617
File: go/apps/api/openapi/openapi.yaml:3309-3312
Timestamp: 2025-07-16T17:51:57.297Z
Learning: In the Unkey API OpenAPI schema, the permissions query regex for the verifyKey endpoint intentionally allows all whitespace characters (including tabs and newlines) via \s. Do not flag this as an error in future reviews.

Learnt from: Flo4604
PR: #3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.699Z
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.

Learnt from: ogzhanolguncu
PR: #3499
File: apps/dashboard/app/new/hooks/use-workspace-step.tsx:19-26
Timestamp: 2025-07-11T13:00:05.416Z
Learning: In the Unkey codebase, ogzhanolguncu prefers to keep commented code for planned future features (like slug-based workspaces) rather than removing it, as it serves as a reference for upcoming implementation.

Learnt from: Flo4604
PR: #3647
File: go/apps/api/openapi/openapi-generated.yaml:3569-3575
Timestamp: 2025-07-22T18:09:41.800Z
Learning: In the Unkey codebase, using non-standard HTTP status code 529 for internal-only endpoints is acceptable and should not be flagged as an issue in future reviews.

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.

Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{go,js,ts,tsx,py,sh,md,txt,json,yaml,yml,ini,env,conf,html,css,scss,xml,c,h,cpp,java,rb,rs,php,pl,sql} : Make sure to add relevant anchor comments whenever a file or piece of code is too complex, very important, confusing, or could have a bug.

Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{go,js,ts,tsx,py,sh,md,txt,json,yaml,yml,ini,env,conf,html,css,scss,xml,c,h,cpp,java,rb,rs,php,pl,sql} : Use AIDEV-NOTE:, AIDEV-TODO:, AIDEV-BUSINESS_RULE:, or AIDEV-QUESTION: (all-caps prefix) as anchor comments aimed at AI and developers.

Learnt from: mcstepp
PR: #3662
File: apps/dashboard/lib/trpc/routers/deployment/getOpenApiDiff.ts:110-147
Timestamp: 2025-07-25T19:11:00.208Z
Learning: In apps/dashboard/lib/trpc/routers/deployment/getOpenApiDiff.ts, the user mcstepp prefers to keep mock data fallbacks in POC/demonstration code for simplicity, even if it wouldn't be production-ready. This aligns with the PR being work-in-progress for demonstration purposes.

Learnt from: mcstepp
PR: #3242
File: apps/dashboard/app/(app)/apis/[apiId]/api-id-navbar.tsx:47-50
Timestamp: 2025-05-15T15:57:02.128Z
Learning: When reviewing code for Unkey, prefer using Boolean() over the double negation (!!) operator for boolean coercion, as their linter rules favor this pattern.

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.

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.

go/apps/api/routes/v2_keys_whoami/handler.go (9)

Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{go,js,ts,tsx,py,sh,md,txt,json,yaml,yml,ini,env,conf,html,css,scss,xml,c,h,cpp,java,rb,rs,php,pl,sql} : Make sure to add relevant anchor comments whenever a file or piece of code is too complex, very important, confusing, or could have a bug.

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.

Learnt from: ogzhanolguncu
PR: #2872
File: apps/dashboard/lib/trpc/routers/ratelimit/createNamespace.ts:36-39
Timestamp: 2025-04-08T09:34:24.576Z
Learning: When querying or updating namespaces in the Unkey dashboard, always scope the operations to the current workspace using eq(table.workspaceId, ctx.workspace.id) to prevent cross-workspace access.

Learnt from: Flo4604
PR: #3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.699Z
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.

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.

Learnt from: chronark
PR: #3617
File: go/apps/api/openapi/openapi.yaml:3309-3312
Timestamp: 2025-07-16T17:51:57.297Z
Learning: In the Unkey API OpenAPI schema, the permissions query regex for the verifyKey endpoint intentionally allows all whitespace characters (including tabs and newlines) via \s. Do not flag this as an error in future reviews.

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.

Learnt from: Flo4604
PR: #3647
File: go/apps/api/openapi/openapi-generated.yaml:3569-3575
Timestamp: 2025-07-22T18:09:41.800Z
Learning: In the Unkey codebase, using non-standard HTTP status code 529 for internal-only endpoints is acceptable and should not be flagged as an issue in future reviews.

Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{go,js,ts,tsx,py,sh,md,txt,json,yaml,yml,ini,env,conf,html,css,scss,xml,c,h,cpp,java,rb,rs,php,pl,sql} : Use AIDEV-NOTE:, AIDEV-TODO:, AIDEV-BUSINESS_RULE:, or AIDEV-QUESTION: (all-caps prefix) as anchor comments aimed at AI and developers.

go/apps/api/openapi/openapi-generated.yaml (14)

Learnt from: Flo4604
PR: #3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.699Z
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.

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.

Learnt from: chronark
PR: #3617
File: go/apps/api/openapi/openapi.yaml:3309-3312
Timestamp: 2025-07-16T17:51:57.297Z
Learning: In the Unkey API OpenAPI schema, the permissions query regex for the verifyKey endpoint intentionally allows all whitespace characters (including tabs and newlines) via \s. Do not flag this as an error in future reviews.

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.

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.

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.

Learnt from: ogzhanolguncu
PR: #3324
File: apps/dashboard/app/(app)/authorization/roles/components/table/components/actions/keys-table-action.popover.constants.tsx:17-18
Timestamp: 2025-06-19T11:48:05.070Z
Learning: In the authorization roles refactor, the RoleBasic type uses roleId as the property name for the role identifier, not id. This is consistent throughout the codebase in apps/dashboard/lib/trpc/routers/authorization/roles/query.ts.

Learnt from: AkshayBandi027
PR: #2215
File: apps/dashboard/app/(app)/@breadcrumb/authorization/roles/[roleId]/page.tsx:28-29
Timestamp: 2024-10-08T15:33:04.290Z
Learning: In authorization/roles/[roleId]/update-role.tsx, the tag role-${role.id} is revalidated after updating a role to ensure that the caching mechanism is properly handled for roles.

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:468-581
Timestamp: 2025-07-15T14:47:20.490Z
Learning: In the Unkey codebase, role and permission names are validated at the OpenAPI schema layer with strict regex patterns: role names must match "^[a-zA-Z][a-zA-Z0-9_-]*$" (start with letter, followed by letters/numbers/underscores/hyphens) and permission names must match "^[a-zA-Z0-9_]+$" (letters, numbers, underscores only). This validation occurs during zen.BindBody call before handlers run, preventing malicious or improperly formatted names from reaching auto-creation logic.

Learnt from: ogzhanolguncu
PR: #2876
File: apps/dashboard/components/logs/datetime/constants.ts:96-96
Timestamp: 2025-02-06T17:41:47.228Z
Learning: In the Unkey codebase, avoid hardcoding IDs or indices that depend on array positions, as the arrays may be modified in the future. Instead, use methods like find with unique identifiers or properties to locate specific items.

Learnt from: ogzhanolguncu
PR: #3156
File: apps/dashboard/app/(app)/apis/[apiId]/_components/create-key/components/ratelimit-setup.tsx:48-59
Timestamp: 2025-04-22T11:47:24.733Z
Learning: For form inputs in the Unkey dashboard, validation constraints are handled at the schema level using Zod rather than using HTML attributes like min/step on numeric inputs.

Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{env,sh,yaml,yml,json,conf,ini} : All environment variables MUST follow the format UNKEY_<SERVICE_NAME>_VARNAME.

Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{go,js,ts,tsx,py,sh,md,txt,json,yaml,yml,ini,env,conf,html,css,scss,xml,c,h,cpp,java,rb,rs,php,pl,sql} : Use AIDEV-NOTE:, AIDEV-TODO:, AIDEV-BUSINESS_RULE:, or AIDEV-QUESTION: (all-caps prefix) as anchor comments aimed at AI and developers.

Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{go,js,ts,tsx,py,sh,md,txt,json,yaml,yml,ini,env,conf,html,css,scss,xml,c,h,cpp,java,rb,rs,php,pl,sql} : Make sure to add relevant anchor comments whenever a file or piece of code is too complex, very important, confusing, or could have a bug.

🧬 Code Graph Analysis (1)
go/apps/api/routes/v2_keys_get_key/handler.go (2)
go/pkg/db/key_find_by_id_or_hash.sql_generated.go (1)
  • FindKeyByIdOrHashParams (28-31)
go/pkg/db/models_generated.go (1)
  • EncryptedKey (635-642)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Test Go API Local / Test
  • GitHub Check: Test Agent Local / test_agent_local
  • GitHub Check: Build / Build
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Test Packages / Test
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (8)
go/apps/api/routes/v2_keys_get_key/handler.go (2)

62-65: LGTM! Simplified key lookup logic.

The change correctly simplifies the key lookup to only use KeyId, setting the Hash parameter to invalid. This aligns with the PR objective to separate the functionality and remove support for key-based lookup from this endpoint.


161-161: LGTM! Proper encryption check logic.

The conditional correctly checks for both valid encrypted key and encryption key ID before attempting decryption. This ensures we have all necessary components for the decryption operation and is independent of the request format changes.

go/apps/api/openapi/spec/paths/v2/keys/whoami/index.yaml (3)

18-25: LGTM! Proper security and request body configuration.

The security scheme and request body configuration are correctly set up with appropriate schema references and explicit requirements.


26-33: LGTM! Well-defined success response.

The success response is properly configured with appropriate status code, content type, and clear description.


34-63: LGTM! Comprehensive error response coverage.

All relevant HTTP error status codes are properly defined with appropriate descriptions and schema references. The error handling follows consistent patterns with other endpoints in the API.

go/apps/api/routes/v2_keys_whoami/200_test.go (1)

1-355: LGTM! Comprehensive test coverage.

The test file provides excellent coverage for successful key retrieval scenarios, including:

  • Basic key retrieval with encryption
  • Complex nested metadata
  • Expiration timestamps
  • Credits with daily/monthly refills
  • Permissions and roles
  • Multiple ratelimits
  • Disabled keys

All test cases are well-structured with proper assertions.

go/apps/api/routes/v2_keys_whoami/404_test.go (2)

20-51: Well-structured test for non-existent key scenario.

The test correctly validates the 404 response when querying for a key that doesn't exist, with appropriate permission setup and error message verification.


53-224: Comprehensive security test coverage.

Excellent test design that thoroughly validates authorization boundaries:

  • Correctly returns 404 instead of 403 to prevent information leakage
  • Covers all critical access control scenarios (no permissions, wrong permissions, cross-workspace, cross-API)
  • Properly sets up test data with direct database insertions

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@Flo4604 Flo4604 added this pull request to the merge queue Jul 28, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to a conflict with the base branch Jul 28, 2025
@Flo4604 Flo4604 enabled auto-merge July 28, 2025 13:28
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: 1

♻️ Duplicate comments (3)
go/apps/api/openapi/openapi-generated.yaml (3)

2-2: Volatile timestamp line still committed
The # Generated at: line changes on every bundle regeneration and pollutes commit history with noisy diffs. Please drop it from the checked-in file or exclude the whole bundle from VCS.


1424-1432: Key string still lacks a validating regex
Prior feedback suggested adding a simple pattern (e.g. ^sk_[A-Za-z0-9]{32,}$) to reject obviously malformed keys. The property still only uses minLength/maxLength.


5015-5064: operationId & summary are still generic / misleading
operationId: whoami risks collisions and the summary still says “by hash” although the endpoint expects the full key string. See earlier review—recommend renaming to something unique like keysWhoami and correcting the summary.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fa073ad and fae522e.

📒 Files selected for processing (2)
  • go/apps/api/openapi/gen.go (3 hunks)
  • go/apps/api/openapi/openapi-generated.yaml (4 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: Flo4604
PR: unkeyed/unkey#3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.699Z
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.
Learnt from: chronark
PR: unkeyed/unkey#3617
File: go/apps/api/openapi/openapi.yaml:3309-3312
Timestamp: 2025-07-16T17:51:57.297Z
Learning: In the Unkey API OpenAPI schema, the permissions query regex for the verifyKey endpoint intentionally allows all whitespace characters (including tabs and newlines) via `\s`. Do not flag this as an error in future reviews.
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.
Learnt from: chronark
PR: unkeyed/unkey#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.
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3661
File: go/apps/api/routes/v2_identities_update_identity/handler.go:115-119
Timestamp: 2025-07-28T11:47:43.144Z
Learning: The v2 update identity endpoint (go/apps/api/routes/v2_identities_update_identity/handler.go) intentionally uses `ExternalId` field instead of the unified `Identity` field used in other v2 identity endpoints. This is because the update endpoint needs to both find by externalId and potentially update the externalId value, making the specific field name more appropriate than the generic `Identity` field.
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: chronark
PR: unkeyed/unkey#3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.
go/apps/api/openapi/openapi-generated.yaml (16)

Learnt from: Flo4604
PR: #3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.699Z
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.

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.

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.

Learnt from: chronark
PR: #3617
File: go/apps/api/openapi/openapi.yaml:3309-3312
Timestamp: 2025-07-16T17:51:57.297Z
Learning: In the Unkey API OpenAPI schema, the permissions query regex for the verifyKey endpoint intentionally allows all whitespace characters (including tabs and newlines) via \s. Do not flag this as an error in future reviews.

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:353-466
Timestamp: 2025-07-15T14:25:05.608Z
Learning: In the Unkey codebase, input validation for API endpoints is handled at the OpenAPI schema layer, which validates request fields like permission slugs (pattern: "^[a-zA-Z0-9_]+$", length: 1-100 characters) before requests reach the handler code. This validation occurs during the zen.BindBody call in handlers.

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.

Learnt from: ogzhanolguncu
PR: #3324
File: apps/dashboard/app/(app)/authorization/roles/components/table/components/actions/keys-table-action.popover.constants.tsx:17-18
Timestamp: 2025-06-19T11:48:05.070Z
Learning: In the authorization roles refactor, the RoleBasic type uses roleId as the property name for the role identifier, not id. This is consistent throughout the codebase in apps/dashboard/lib/trpc/routers/authorization/roles/query.ts.

Learnt from: AkshayBandi027
PR: #2215
File: apps/dashboard/app/(app)/@breadcrumb/authorization/roles/[roleId]/page.tsx:28-29
Timestamp: 2024-10-08T15:33:04.290Z
Learning: In authorization/roles/[roleId]/update-role.tsx, the tag role-${role.id} is revalidated after updating a role to ensure that the caching mechanism is properly handled for roles.

Learnt from: chronark
PR: #3560
File: go/apps/api/routes/v2_keys_create_key/handler.go:468-581
Timestamp: 2025-07-15T14:47:20.490Z
Learning: In the Unkey codebase, role and permission names are validated at the OpenAPI schema layer with strict regex patterns: role names must match "^[a-zA-Z][a-zA-Z0-9_-]*$" (start with letter, followed by letters/numbers/underscores/hyphens) and permission names must match "^[a-zA-Z0-9_]+$" (letters, numbers, underscores only). This validation occurs during zen.BindBody call before handlers run, preventing malicious or improperly formatted names from reaching auto-creation logic.

Learnt from: ogzhanolguncu
PR: #2876
File: apps/dashboard/components/logs/datetime/constants.ts:96-96
Timestamp: 2025-02-06T17:41:47.228Z
Learning: In the Unkey codebase, avoid hardcoding IDs or indices that depend on array positions, as the arrays may be modified in the future. Instead, use methods like find with unique identifiers or properties to locate specific items.

Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{env,sh,yaml,yml,json,conf,ini} : All environment variables MUST follow the format UNKEY_<SERVICE_NAME>_VARNAME.

Learnt from: ogzhanolguncu
PR: #3156
File: apps/dashboard/app/(app)/apis/[apiId]/_components/create-key/components/ratelimit-setup.tsx:48-59
Timestamp: 2025-04-22T11:47:24.733Z
Learning: For form inputs in the Unkey dashboard, validation constraints are handled at the schema level using Zod rather than using HTML attributes like min/step on numeric inputs.

Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{go,js,ts,tsx,py,sh,md,txt,json,yaml,yml,ini,env,conf,html,css,scss,xml,c,h,cpp,java,rb,rs,php,pl,sql} : Use AIDEV-NOTE:, AIDEV-TODO:, AIDEV-BUSINESS_RULE:, or AIDEV-QUESTION: (all-caps prefix) as anchor comments aimed at AI and developers.

Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{go,js,ts,tsx,py,sh,md,txt,json,yaml,yml,ini,env,conf,html,css,scss,xml,c,h,cpp,java,rb,rs,php,pl,sql} : Make sure to add relevant anchor comments whenever a file or piece of code is too complex, very important, confusing, or could have a bug.

Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{go,js,ts,tsx,py,sh,md,txt,json,yaml,yml,ini,env,conf,html,css,scss,xml,c,h,cpp,java,rb,rs,php,pl,sql} : Do not remove AIDEV-*s without explicit human instruction.

Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/deploy/{assetmanagerd,billaged,builderd,metald}/**/*.go : When a service's *.go code changes significantly, increase the patch-level version number.

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

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.

Learnt from: ogzhanolguncu
PR: #3661
File: go/apps/api/routes/v2_identities_update_identity/handler.go:115-119
Timestamp: 2025-07-28T11:47:43.144Z
Learning: The v2 update identity endpoint (go/apps/api/routes/v2_identities_update_identity/handler.go) intentionally uses ExternalId field instead of the unified Identity field used in other v2 identity endpoints. This is because the update endpoint needs to both find by externalId and potentially update the externalId value, making the specific field name more appropriate than the generic Identity field.

🧬 Code Graph Analysis (1)
go/apps/api/openapi/gen.go (2)
go/pkg/db/models_generated.go (1)
  • Key (666-690)
go/pkg/codes/unkey_data.go (1)
  • Data (87-128)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Test Agent Local / test_agent_local
  • GitHub Check: Test Go API Local / Test
  • GitHub Check: Build / Build
  • GitHub Check: Test Packages / Test
  • GitHub Check: autofix
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (4)
go/apps/api/openapi/gen.go (4)

1022-1022: LGTM! KeyId field correctly made mandatory.

The change from pointer to non-pointer string correctly enforces that keyId is now required for all key retrieval requests, aligning with the PR objective to remove the oneOf constraint and make this field mandatory.


1532-1538: LGTM! Well-defined request body for whoami endpoint.

The new V2KeysWhoamiRequestBody struct correctly defines the request structure for the whoami endpoint with:

  • Required Key field for the complete API key string
  • Comprehensive documentation with appropriate security warnings
  • Clear guidance about including the full key with prefix

1540-1546: LGTM! Consistent response body structure.

The new V2KeysWhoamiResponseBody struct correctly defines the response structure by:

  • Reusing the existing KeyResponseData type for consistency
  • Including the standard Meta field for request metadata
  • Following the established response body pattern used throughout the API

2167-2168: LGTM! Consistent JSON request body alias.

The new WhoamiJSONRequestBody alias correctly follows the established pattern in the codebase for JSON request body type aliases, providing the necessary type binding for the HTTP handler.

@Flo4604 Flo4604 added this pull request to the merge queue Jul 28, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jul 28, 2025
@Flo4604 Flo4604 added this pull request to the merge queue Jul 28, 2025
Merged via the queue into main with commit 5741b27 Jul 28, 2025
18 checks passed
@Flo4604 Flo4604 deleted the 07-28-feat__v2_keys.whoami_endpoint_separate_from_getkey branch July 28, 2025 14:53
@coderabbitai coderabbitai bot mentioned this pull request Aug 15, 2025
18 tasks
@coderabbitai coderabbitai bot mentioned this pull request Sep 12, 2025
18 tasks
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.

2 participants