Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions deployment/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ services:
UNKEY_DATABASE_PRIMARY: "unkey:password@tcp(mysql:3306)/unkey?parseTime=true"
UNKEY_CLICKHOUSE_URL: "clickhouse://default:password@clickhouse:9000?secure=false&skip_verify=true"
UNKEY_CHPROXY_AUTH_TOKEN: "chproxy-test-token-123"
UNKEY_VAULT_AUTH_TOKEN: "vault-test-token-456"
UNKEY_OTEL: true
OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel:4318"
OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf"
Expand Down
5 changes: 5 additions & 0 deletions go/apps/api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ type Config struct {

// ChproxyToken is the authentication token for ClickHouse proxy endpoints
ChproxyToken string

// --- Vault configuration ---

// VaultToken is the authentication token for vault endpoints
VaultToken string
}

func (c Config) Validate() error {
Expand Down
39 changes: 39 additions & 0 deletions go/apps/api/openapi/gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

127 changes: 127 additions & 0 deletions go/apps/api/openapi/openapi-generated.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,57 @@ components:
type: string
description: Processing status
example: "OK"
InternalVaultDecryptRequestBody:
type: object
required:
- keyring
- encrypted
properties:
keyring:
type: string
description: The keyring identifier used for encryption
example: "user_data"
encrypted:
type: string
description: Base64 encoded encrypted data to decrypt
example: "eyJhbGdvcml0aG0iOiJBRVMtMjU2LUdDTSIsIm5vbmNlIjoi..."
Comment on lines +97 to +110
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Mark base-64 blob fields with an explicit format: byte.

OpenAPI uses format: byte to denote base-64 encoded strings.
Without it, generators may treat the value as arbitrary UTF-8 text and silently corrupt binary payloads.

-                encrypted:
-                    type: string
+                encrypted:
+                    type: string
+                    format: byte

(Do the same for any other encrypted/ciphertext properties.)

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
InternalVaultDecryptRequestBody:
type: object
required:
- keyring
- encrypted
properties:
keyring:
type: string
description: The keyring identifier used for encryption
example: "user_data"
encrypted:
type: string
description: Base64 encoded encrypted data to decrypt
example: "eyJhbGdvcml0aG0iOiJBRVMtMjU2LUdDTSIsIm5vbmNlIjoi..."
InternalVaultDecryptRequestBody:
type: object
required:
- keyring
- encrypted
properties:
keyring:
type: string
description: The keyring identifier used for encryption
example: "user_data"
encrypted:
type: string
format: byte
description: Base64 encoded encrypted data to decrypt
example: "eyJhbGdvcml0aG0iOiJBRVMtMjU2LUdDTSIsIm5vbmNlIjoi..."
🤖 Prompt for AI Agents
In go/apps/api/openapi/openapi-generated.yaml around lines 97 to 110, the
properties representing base64 encoded data, such as "encrypted", lack the
explicit "format: byte" annotation. Add "format: byte" to these properties to
correctly indicate they contain base64 encoded binary data, preventing
generators from misinterpreting them as UTF-8 text. Apply this change to all
similar fields like "encrypted" or "ciphertext" throughout the file.

InternalVaultDecryptResponseBody:
type: object
required:
- plaintext
properties:
plaintext:
type: string
description: The decrypted plaintext data
example: "sensitive information"
InternalVaultEncryptRequestBody:
type: object
required:
- keyring
- data
properties:
keyring:
type: string
description: The keyring identifier to use for encryption
example: "user_data"
data:
type: string
description: The plaintext data to encrypt
example: "sensitive information"
InternalVaultEncryptResponseBody:
type: object
required:
- encrypted
- keyId
properties:
encrypted:
type: string
description: Base64 encoded encrypted data
example: "eyJhbGdvcml0aG0iOiJBRVMtMjU2LUdDTSIsIm5vbmNlIjoi..."
keyId:
type: string
description: The ID of the data encryption key used
example: "dek_12345"
Comment on lines +140 to +147
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Repeat the format: byte hint for the encryption response.

Same reasoning as above – generators and clients benefit from the correct semantic hint.

-                encrypted:
-                    type: string
+                encrypted:
+                    type: string
+                    format: byte
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
encrypted:
type: string
description: Base64 encoded encrypted data
example: "eyJhbGdvcml0aG0iOiJBRVMtMjU2LUdDTSIsIm5vbmNlIjoi..."
keyId:
type: string
description: The ID of the data encryption key used
example: "dek_12345"
encrypted:
type: string
format: byte
description: Base64 encoded encrypted data
example: "eyJhbGdvcml0aG9yaXRobSI6IkFFUy0yNTYtR0NNIiwibm9uY2UiOiIifQ=="
keyId:
type: string
description: The ID of the data encryption key used
example: "dek_12345"
🤖 Prompt for AI Agents
In go/apps/api/openapi/openapi-generated.yaml around lines 140 to 147, the
encryption response fields lack the 'format: byte' hint which helps generators
and clients interpret the data correctly. Add 'format: byte' to the 'encrypted'
field to indicate it is base64-encoded binary data, ensuring proper semantic
understanding by tools consuming this schema.

V2ApisCreateApiRequestBody:
type: object
required:
Expand Down Expand Up @@ -3149,6 +3200,82 @@ paths:
- chproxy
x-excluded: true
x-speakeasy-ignore: true
/_internal/vault/decrypt:
post:
description: |-
Internal endpoint for decrypting data using the vault service. This endpoint is used internally by the API and should not be used by external clients.

This endpoint bypasses normal authentication and validation as it's intended for internal use only.
operationId: internalVaultDecrypt
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/InternalVaultDecryptRequestBody'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/InternalVaultDecryptResponseBody'
description: Data successfully decrypted
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/BadRequestErrorResponse'
description: Invalid request body
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/InternalServerErrorResponse'
description: Internal server error during decryption
security: []
Comment on lines +3203 to +3235
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Spec is missing 401 response & security scheme despite token enforcement.

Handlers reject requests when the static vault token is absent or wrong, yet the spec declares security: [] and no 401 response.
This divergence breaks contract-tests and service discovery tooling.

            security: []
+            responses:
+                "401":
+                    description: Invalid or missing Vault auth token
+                    content:
+                        application/json:
+                            schema:
+                                $ref: '#/components/schemas/UnauthorizedErrorResponse'
+
+            security:
+                - VaultStaticToken: []

Add a components.securitySchemes.VaultStaticToken mirroring the existing StaticToken pattern used elsewhere (header‐based, no scopes).

If the endpoint truly must stay undocumented, keep x-excluded: true but still describe real behaviour for internal consumers.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In go/apps/api/openapi/openapi-generated.yaml between lines 3203 and 3235, the
endpoint /_internal/vault/decrypt incorrectly declares no security and lacks a
401 response despite enforcing a static vault token. Add a VaultStaticToken
security scheme under components.securitySchemes similar to the existing
StaticToken scheme, then update the endpoint's security field to require this
VaultStaticToken. Also, add a 401 response describing unauthorized access due to
missing or invalid token. If the endpoint must remain undocumented, add
x-excluded: true but keep these security details to reflect actual behavior.

summary: Internal vault decryption endpoint
tags:
- _internal
x-excluded: true
x-speakeasy-ignore: true
/_internal/vault/encrypt:
post:
description: |-
Internal endpoint for encrypting data using the vault service. This endpoint is used internally by the API and should not be used by external clients.

This endpoint bypasses normal authentication and validation as it's intended for internal use only.
operationId: internalVaultEncrypt
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/InternalVaultEncryptRequestBody'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/InternalVaultEncryptResponseBody'
description: Data successfully encrypted
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/BadRequestErrorResponse'
description: Invalid request body
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/InternalServerErrorResponse'
description: Internal server error during encryption
security: []
summary: Internal vault encryption endpoint
Comment on lines +3242 to +3274
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Same 401 / security concern for the encryption endpoint.

Apply the identical 401 response and VaultStaticToken security scheme here to avoid inconsistency with the decryption route and actual runtime behaviour.

🤖 Prompt for AI Agents
In go/apps/api/openapi/openapi-generated.yaml between lines 3242 and 3274, the
internalVaultEncrypt POST endpoint lacks the 401 response and VaultStaticToken
security scheme, causing inconsistency with the decryption endpoint and runtime
behavior. Add a 401 response with the appropriate schema and description, and
include the VaultStaticToken security scheme under the security section to align
with the decryption route's authentication setup.

tags:
- _internal
x-excluded: true
x-speakeasy-ignore: true
/v2/apis.createApi:
post:
description: |
Expand Down
12 changes: 9 additions & 3 deletions go/apps/api/openapi/openapi-split.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,17 @@ paths:

# ClickHouse Proxy Endpoints (Internal)
/_internal/chproxy/verifications:
$ref: "./spec/paths/chproxy/verifications/index.yaml"
$ref: "./spec/paths/_internal/chproxy/verifications/index.yaml"
/_internal/chproxy/metrics:
$ref: "./spec/paths/chproxy/metrics/index.yaml"
$ref: "./spec/paths/_internal/chproxy/metrics/index.yaml"
/_internal/chproxy/ratelimits:
$ref: "./spec/paths/chproxy/ratelimits/index.yaml"
$ref: "./spec/paths/_internal/chproxy/ratelimits/index.yaml"

# Vault Endpoints (Internal)
/_internal/vault/encrypt:
$ref: "./spec/paths/_internal/vault/encrypt/index.yaml"
/_internal/vault/decrypt:
$ref: "./spec/paths/_internal/vault/decrypt/index.yaml"

components:
securitySchemes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ post:
content:
application/json:
schema:
$ref: "../../../error/BadRequestErrorResponse.yaml"
$ref: "../../../../error/BadRequestErrorResponse.yaml"
description: Invalid request body or malformed events
"529":
content:
application/json:
schema:
$ref: "../../../error/InternalServerErrorResponse.yaml"
$ref: "../../../../error/InternalServerErrorResponse.yaml"
description: Service overloaded, unable to process events
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ post:
content:
application/json:
schema:
$ref: "../../../error/BadRequestErrorResponse.yaml"
$ref: "../../../../error/BadRequestErrorResponse.yaml"
description: Invalid request body or malformed events
"529":
content:
application/json:
schema:
$ref: "../../../error/InternalServerErrorResponse.yaml"
$ref: "../../../../error/InternalServerErrorResponse.yaml"
description: Service overloaded, unable to process events
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ post:
content:
application/json:
schema:
$ref: "../../../error/BadRequestErrorResponse.yaml"
$ref: "../../../../error/BadRequestErrorResponse.yaml"
description: Invalid request body or malformed events
"529":
content:
application/json:
schema:
$ref: "../../../error/InternalServerErrorResponse.yaml"
$ref: "../../../../error/InternalServerErrorResponse.yaml"
description: Service overloaded, unable to process events
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type: object
required:
- keyring
- encrypted
properties:
Copy link
Member

Choose a reason for hiding this comment

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

Can we just make this an array to support decrypting multiple data pieces? This would help with the listKeys endpoin to just do a single req

keyring:
type: string
description: The keyring identifier used for encryption
example: "user_data"
Comment on lines +6 to +9
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Fix inconsistent keyring example and missing newline.

The keyring example "user_data" is inconsistent with the encrypt schema, which states the keyring is "always the workspace id" with example "ws_123". Consider aligning the examples for consistency.

   keyring:
     type: string
     description: The keyring identifier used for encryption
-    example: "user_data"
+    example: "ws_123"
   encrypted:
     type: string
     description: Base64 encoded encrypted data to decrypt
-    example: "eyJhbGdvcml0aG0iOiJBRVMtMjU2LUdDTSIsIm5vbmNlIjoi..."
+    example: "eyJhbGdvcml0aG0iOiJBRVMtMjU2LUdDTSIsIm5vbmNlIjoi..."
+
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
keyring:
type: string
description: The keyring identifier used for encryption
example: "user_data"
keyring:
type: string
description: The keyring identifier used for encryption
example: "ws_123"
encrypted:
type: string
description: Base64 encoded encrypted data to decrypt
example: "eyJhbGdvcml0aG0iOiJBRVMtMjU2LUdDTSIsIm5vbmNlIjoi..."
🤖 Prompt for AI Agents
In
go/apps/api/openapi/spec/paths/_internal/vault/decrypt/InternalVaultDecryptRequestBody.yaml
around lines 6 to 9, the example value for the keyring field is inconsistent
with the encrypt schema. Update the example from "user_data" to "ws_123" to
align with the workspace id usage described in the encrypt schema. Also, ensure
there is a newline after the keyring example for proper YAML formatting.

encrypted:
type: string
description: Base64 encoded encrypted data to decrypt
example: "eyJhbGdvcml0aG0iOiJBRVMtMjU2LUdDTSIsIm5vbmNlIjoi..."
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
type: object
required:
- plaintext
properties:
plaintext:
type: string
description: The decrypted plaintext data
example: "sensitive information"
Comment on lines +1 to +8
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add missing newline at end of file.

The YAML file is missing a newline character at the end, which is flagged by YAMLlint. This is commonly required by YAML standards and many linters.

 properties:
   plaintext:
     type: string
     description: The decrypted plaintext data
-    example: "sensitive information"
+    example: "sensitive information"
+
🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 8-8: no new line character at the end of file

(new-line-at-end-of-file)

🤖 Prompt for AI Agents
In
go/apps/api/openapi/spec/paths/_internal/vault/decrypt/InternalVaultDecryptResponseBody.yaml
at lines 1 to 8, add a newline character at the end of the file to comply with
YAML standards and satisfy YAMLlint requirements.

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
post:
x-speakeasy-ignore: true
x-excluded: true
tags:
- _internal
security: []
operationId: internalVaultDecrypt
summary: Internal vault decryption endpoint
description: |-
Internal endpoint for decrypting data using the vault service. This endpoint is used internally by the API and should not be used by external clients.
This endpoint bypasses normal authentication and validation as it's intended for internal use only.
requestBody:
required: true
content:
application/json:
schema:
"$ref": "./InternalVaultDecryptRequestBody.yaml"
responses:
"200":
content:
application/json:
schema:
"$ref": "./InternalVaultDecryptResponseBody.yaml"
description: Data successfully decrypted
"400":
content:
application/json:
schema:
$ref: "../../../../error/BadRequestErrorResponse.yaml"
description: Invalid request body
"500":
content:
application/json:
schema:
$ref: "../../../../error/InternalServerErrorResponse.yaml"
description: Internal server error during decryption
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Add missing newline at end of file.

Static analysis detected a missing newline character at the end of the file.

-      description: Internal server error during decryption
+      description: Internal server error during decryption
+
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
description: Internal server error during decryption
description: Internal server error during decryption
🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 37-37: no new line character at the end of file

(new-line-at-end-of-file)

🤖 Prompt for AI Agents
In go/apps/api/openapi/spec/paths/_internal/vault/decrypt/index.yaml at line 37,
add a newline character at the end of the file to comply with standard file
formatting and satisfy static analysis checks.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type: object
required:
- keyring
- data
properties:
keyring:
type: string
description: The keyring identifier to use for encryption. This is always the workspace id.
example: "ws_123"
data:
type: string
description: The plaintext data to encrypt
example: "sensitive information"
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type: object
required:
- encrypted
- keyId
properties:
encrypted:
type: string
description: Base64 encoded encrypted data
example: "eyJhbGdvcml0aG0iOiJBRVMtMjU2LUdDTSIsIm5vbmNlIjoi..."
keyId:
type: string
description: The ID of the data encryption key used
example: "dek_12345"
Comment on lines +1 to +13
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Well-designed response schema with minor formatting fix needed.

The schema correctly defines the essential properties for an encryption response - the encrypted data and key ID. The descriptions and examples are clear and helpful.

   keyId:
     type: string
     description: The ID of the data encryption key used
     example: "dek_12345"
+
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type: object
required:
- encrypted
- keyId
properties:
encrypted:
type: string
description: Base64 encoded encrypted data
example: "eyJhbGdvcml0aG0iOiJBRVMtMjU2LUdDTSIsIm5vbmNlIjoi..."
keyId:
type: string
description: The ID of the data encryption key used
example: "dek_12345"
type: object
required:
- encrypted
- keyId
properties:
encrypted:
type: string
description: Base64 encoded encrypted data
example: "eyJhbGdvcml0aG0iOiJBRVMtMjU2LUdDTSIsIm5vbmNlIjoi..."
keyId:
type: string
description: The ID of the data encryption key used
example: "dek_12345"
🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 13-13: no new line character at the end of file

(new-line-at-end-of-file)

🤖 Prompt for AI Agents
In
go/apps/api/openapi/spec/paths/_internal/vault/encrypt/InternalVaultEncryptResponseBody.yaml
lines 1 to 13, the response schema is well defined but requires a minor
formatting fix. Ensure proper indentation and spacing are consistent throughout
the YAML file to maintain readability and adhere to YAML standards. Verify that
all keys and values align correctly under their respective parent nodes.

Loading
Loading