add platform api changes for event gateway hmac secret generation#2237
Conversation
|
Warning Review limit reached
More reviews will be available in 45 minutes and 7 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses rolling per-developer review limits. Reviews become available again as older review attempts age out of the rolling limit window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughThis PR introduces end-to-end WebSub API HMAC secret management for inbound webhook verification. The platform-API side adds a Suggested reviewers
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (2)
platform-api/src/internal/service/gateway_events.go (1)
192-203: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winReject unsupported actions instead of silently mapping to UPDATED.
Line 201 silently coerces invalid actions, which can produce incorrect event semantics. Prefer returning an error for unknown values.
Suggested change
func (s *GatewayEventsService) BroadcastWebSubAPIHmacSecretEvent(gatewayID, action string, event *model.WebSubAPIHmacSecretEvent) error { var eventType string switch action { case "CREATED": eventType = EventTypeWebSubAPIHmacSecretCreated case "UPDATED": eventType = EventTypeWebSubAPIHmacSecretUpdated case "DELETED": eventType = EventTypeWebSubAPIHmacSecretDeleted default: - eventType = EventTypeWebSubAPIHmacSecretUpdated + return fmt.Errorf("unsupported hmac secret action: %s", action) } return s.broadcastEvent(gatewayID, eventType, event) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@platform-api/src/internal/service/gateway_events.go` around lines 192 - 203, The default case in the switch statement within the BroadcastWebSubAPIHmacSecretEvent method currently silently maps unknown actions to EventTypeWebSubAPIHmacSecretUpdated, which masks unsupported input. Replace the default case to return an error instead of coercing invalid actions, ensuring that only the supported actions (CREATED, UPDATED, DELETED) are processed and unknown actions are explicitly rejected with a descriptive error message.platform-api/src/api/generated.go (1)
473-478: 🧹 Nitpick | 🔵 Trivial | 💤 Low valueInconsistent naming for WebSub visibility constants.
The generated constants
PrivateandPubliclack the type prefix, unlike the WebBroker equivalents (WebBrokerAPIDevPortalResponseVisibilityPrivate/Public). This may cause naming conflicts. If this is a code-generation artifact, consider updating the OpenAPI spec to ensure consistent naming.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@platform-api/src/api/generated.go` around lines 473 - 478, The constants Private and Public for WebSubAPIDevPortalResponseVisibility lack the type prefix that exists in the equivalent WebBrokerAPIDevPortalResponseVisibility constants, creating potential naming conflicts. Rename the Private constant to WebSubAPIDevPortalResponseVisibilityPrivate and the Public constant to WebSubAPIDevPortalResponseVisibilityPublic to maintain consistency with the WebBroker equivalents. If this is generated code from an OpenAPI spec, ensure the spec is updated to produce consistent naming patterns across all visibility constant definitions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@gateway/gateway-controller/pkg/controlplane/client.go`:
- Around line 2499-2512: The RemoveAllByAPI error handler currently logs a
warning but continues to the Store loop, which can leave old and new secrets
mixed together and break the intended clear-and-replace behavior. Modify the
error handling for the RemoveAllByAPI call on the webhookSecretStore to abort
the entire operation by returning early or skipping the subsequent for loop that
stores new secrets, ensuring that the Store operations only execute if the
RemoveAllByAPI call succeeds.
In `@platform-api/src/config/config.go`:
- Around line 179-183: The HMACSecretEncryptionKey field is missing the koanf
tag and corresponding mapping in the envToKoanfKey function. Add a koanf tag to
the HMACSecretEncryptionKey struct field following the naming pattern of other
fields, and add a case statement in the envToKoanfKey function to map the
environment variable DATABASE_HMAC_SECRET_ENCRYPTION_KEY to the appropriate
koanf key path (following the same pattern as SubscriptionTokenEncryptionKey).
This ensures the environment variable will be properly loaded by the koanf
config mechanism.
In `@platform-api/src/internal/handler/websub_api_hmac_secret.go`:
- Around line 239-241: In the case statement handling errors.Is(err,
constants.ErrHmacSecretEncryptionKeyMissing), change the HTTP status code from
http.StatusInternalServerError (500) to http.StatusServiceUnavailable (503) to
align with the OpenAPI spec which defines 503 as the response for when HMAC
secret management is not configured. Keep the error message the same.
In `@platform-api/src/internal/service/websub_api_hmac_secret.go`:
- Around line 91-97: The current logic in the slugifyHmacSecret function
truncates the name to 63 characters, but when the name becomes empty and a
fallback value is assigned (name = "secret-" + apiHandle), there is no length
enforcement on this fallback. After the fallback name assignment, reapply the
max-length truncation logic to ensure the final name does not exceed 63
characters, matching the enforcement applied before the fallback assignment.
In `@platform-api/src/resources/gateway-internal-api.yaml`:
- Around line 819-825: The OpenAPI specification for this endpoint is missing
the 503 Service Unavailable response definition even though the handler returns
this status when HMAC secret management is not configured. Add a 503 response
entry after the existing 500 response in the responses section, with appropriate
description documenting the service-not-configured state, and include the same
ErrorResponse schema reference to align the spec with the actual runtime
behavior.
In `@platform-api/src/resources/openapi.yaml`:
- Around line 5804-5809: The regenerate endpoint's requestBody references the
WebSubAPIHmacSecretRequest schema which requires a displayName field, but this
conflicts with the regenerate contract where only a new secret value should be
needed (since the secret is already identified by secretName in the path).
Create a new schema specifically for the regenerate request (for example,
WebSubAPIHmacSecretRegenerateRequest) that only requires the secret field
without displayName, then update the requestBody reference in the regenerate
endpoint to use this new schema instead of WebSubAPIHmacSecretRequest.
---
Nitpick comments:
In `@platform-api/src/api/generated.go`:
- Around line 473-478: The constants Private and Public for
WebSubAPIDevPortalResponseVisibility lack the type prefix that exists in the
equivalent WebBrokerAPIDevPortalResponseVisibility constants, creating potential
naming conflicts. Rename the Private constant to
WebSubAPIDevPortalResponseVisibilityPrivate and the Public constant to
WebSubAPIDevPortalResponseVisibilityPublic to maintain consistency with the
WebBroker equivalents. If this is generated code from an OpenAPI spec, ensure
the spec is updated to produce consistent naming patterns across all visibility
constant definitions.
In `@platform-api/src/internal/service/gateway_events.go`:
- Around line 192-203: The default case in the switch statement within the
BroadcastWebSubAPIHmacSecretEvent method currently silently maps unknown actions
to EventTypeWebSubAPIHmacSecretUpdated, which masks unsupported input. Replace
the default case to return an error instead of coercing invalid actions,
ensuring that only the supported actions (CREATED, UPDATED, DELETED) are
processed and unknown actions are explicitly rejected with a descriptive error
message.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 98e4f5a1-baa3-470d-922b-20c9c4999616
📒 Files selected for processing (24)
gateway/gateway-controller/cmd/controller/main.gogateway/gateway-controller/pkg/controlplane/client.gogateway/gateway-controller/pkg/controlplane/client_integration_test.gogateway/gateway-controller/pkg/controlplane/controlplane_test.gogateway/gateway-controller/pkg/utils/api_utils.goplatform-api/src/api/generated.goplatform-api/src/api/manual_types.goplatform-api/src/api/websub_hmac_secret.goplatform-api/src/config/config.goplatform-api/src/internal/constants/error.goplatform-api/src/internal/database/schema.postgres.sqlplatform-api/src/internal/database/schema.sqlplatform-api/src/internal/database/schema.sqlite.sqlplatform-api/src/internal/dto/gateway_internal.goplatform-api/src/internal/handler/gateway_internal.goplatform-api/src/internal/handler/websub_api_hmac_secret.goplatform-api/src/internal/model/websub_api_hmac_secret.goplatform-api/src/internal/repository/interfaces.goplatform-api/src/internal/repository/websub_api_hmac_secret.goplatform-api/src/internal/server/server.goplatform-api/src/internal/service/gateway_events.goplatform-api/src/internal/service/websub_api_hmac_secret.goplatform-api/src/resources/gateway-internal-api.yamlplatform-api/src/resources/openapi.yaml
e6a92a7 to
29f3c04
Compare
29f3c04 to
f51e579
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
platform-api/src/internal/service/websub_api_hmac_secret_test.go (1)
128-234: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd test coverage for name generation boundary conditions.
The Generate tests cover core functionality well but miss three boundary cases in the name generation logic (from service code):
- Display names that slugify to >63 characters (triggering truncation).
- Display names that slugify to empty strings (triggering fallback to "secret-" + apiHandle).
- Very long apiHandle values where the fallback name itself exceeds 63 characters (triggering second truncation).
These are distinct conditional branches in production code that should have explicit test coverage to prevent bugs in identifier generation.
Suggested test cases
// TestWebSubAPIHmacSecret_Generate_LongDisplayNameTruncated verifies that // display names longer than 63 chars are truncated after slugification. func TestWebSubAPIHmacSecret_Generate_LongDisplayNameTruncated(t *testing.T) { websubRepo := newMockWebSubAPIRepository() withWebSubAPI(websubRepo) hmacRepo := newMockHmacSecretRepo() svc := buildHmacSecretService(t, websubRepo, hmacRepo) longName := strings.Repeat("verylongname-", 10) // >63 chars after slug meta, _, err := svc.Generate("org-uuid", "test-api", longName, "") if err != nil { t.Fatalf("Generate with long name failed: %v", err) } if len(meta.Name) != 63 { t.Errorf("expected name truncated to 63 chars, got %d", len(meta.Name)) } } // TestWebSubAPIHmacSecret_Generate_EmptySlugFallback verifies that // display names that slugify to empty trigger fallback name generation. func TestWebSubAPIHmacSecret_Generate_EmptySlugFallback(t *testing.T) { websubRepo := newMockWebSubAPIRepository() withWebSubAPI(websubRepo) hmacRepo := newMockHmacSecretRepo() svc := buildHmacSecretService(t, websubRepo, hmacRepo) meta, _, err := svc.Generate("org-uuid", "test-api", "!@#$%^", "") if err != nil { t.Fatalf("Generate with special-char-only name failed: %v", err) } if meta.Name != "secret-test-api" { t.Errorf("expected fallback name 'secret-test-api', got %q", meta.Name) } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@platform-api/src/internal/service/websub_api_hmac_secret_test.go` around lines 128 - 234, The test file is missing coverage for three boundary conditions in the name generation logic of the Generate method. Add three new test functions to cover: (1) display names longer than 63 characters that get truncated after slugification by verifying the returned meta.Name length equals 63, (2) display names containing only special characters that slugify to empty strings by verifying the fallback generates a name in the format "secret-{apiHandle}", and (3) very long apiHandle values where the fallback name itself exceeds 63 characters by verifying the truncation occurs on the fallback. Follow the existing test structure in the file (using newMockWebSubAPIRepository, newMockHmacSecretRepo, buildHmacSecretService, and calling svc.Generate) to ensure consistency with the current test patterns.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@platform-api/src/internal/database/schema.sqlserver.sql`:
- Around line 395-405: The FOREIGN KEY constraint on project_uuid in the
mcp_proxies table uses ON DELETE CASCADE, which causes automatic deletion of
mcp_proxy records when a project is deleted. However, the application manages
mcp_proxies cleanup at the application layer and expects the database to prevent
project deletion until dependent records are handled. Change the ON DELETE
CASCADE clause on line 404 (the FOREIGN KEY constraint referencing
projects(uuid)) to ON DELETE NO ACTION to enforce this contract and allow the
application to control the cleanup order.
In `@platform-api/src/internal/server/server.go`:
- Around line 237-241: The current logic derives an HMAC encryption key from
cfg.Auth.JWT.SecretKey even when that secret is empty, which produces a valid
hash and masks the missing-key error. Fix this by adding an additional check to
ensure cfg.Auth.JWT.SecretKey is not empty before performing the sha256 hashing
and hex encoding. Only apply the fallback key derivation when both
hmacEncryptionKey is empty AND cfg.Auth.JWT.SecretKey is non-empty, otherwise
leave hmacEncryptionKey empty so the missing-key validation path is properly
triggered.
---
Nitpick comments:
In `@platform-api/src/internal/service/websub_api_hmac_secret_test.go`:
- Around line 128-234: The test file is missing coverage for three boundary
conditions in the name generation logic of the Generate method. Add three new
test functions to cover: (1) display names longer than 63 characters that get
truncated after slugification by verifying the returned meta.Name length equals
63, (2) display names containing only special characters that slugify to empty
strings by verifying the fallback generates a name in the format
"secret-{apiHandle}", and (3) very long apiHandle values where the fallback name
itself exceeds 63 characters by verifying the truncation occurs on the fallback.
Follow the existing test structure in the file (using
newMockWebSubAPIRepository, newMockHmacSecretRepo, buildHmacSecretService, and
calling svc.Generate) to ensure consistency with the current test patterns.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e215386e-064e-4cd4-9038-4157d14f9c9a
📒 Files selected for processing (37)
.github/workflows/event-gateway-integration-test-postgres.yml.github/workflows/event-gateway-integration-test-sqlserver.ymlevent-gateway/docker-compose.test.postgres.yamlevent-gateway/docker-compose.test.sqlserver.yamlevent-gateway/it/Makefileevent-gateway/it/features/websub-webhook-secrets.featureevent-gateway/it/suite_test.gogateway/gateway-controller/cmd/controller/main.gogateway/gateway-controller/pkg/controlplane/client.gogateway/gateway-controller/pkg/controlplane/client_integration_test.gogateway/gateway-controller/pkg/controlplane/controlplane_test.gogateway/gateway-controller/pkg/storage/gateway-controller-db.postgres.sqlgateway/gateway-controller/pkg/storage/gateway-controller-db.sqlserver.sqlgateway/gateway-controller/pkg/utils/api_utils.goplatform-api/src/api/generated.goplatform-api/src/api/manual_types.goplatform-api/src/api/websub_hmac_secret.goplatform-api/src/config/config.goplatform-api/src/internal/constants/error.goplatform-api/src/internal/database/schema.postgres.sqlplatform-api/src/internal/database/schema.sqlplatform-api/src/internal/database/schema.sqlite.sqlplatform-api/src/internal/database/schema.sqlserver.sqlplatform-api/src/internal/dto/gateway_internal.goplatform-api/src/internal/handler/gateway_internal.goplatform-api/src/internal/handler/websub_api_hmac_secret.goplatform-api/src/internal/integration/cascade_test.goplatform-api/src/internal/integration/lifecycle_test.goplatform-api/src/internal/model/websub_api_hmac_secret.goplatform-api/src/internal/repository/interfaces.goplatform-api/src/internal/repository/websub_api_hmac_secret.goplatform-api/src/internal/server/server.goplatform-api/src/internal/service/gateway_events.goplatform-api/src/internal/service/websub_api_hmac_secret.goplatform-api/src/internal/service/websub_api_hmac_secret_test.goplatform-api/src/resources/gateway-internal-api.yamlplatform-api/src/resources/openapi.yaml
✅ Files skipped from review due to trivial changes (3)
- platform-api/src/api/websub_hmac_secret.go
- platform-api/src/internal/constants/error.go
- platform-api/src/api/generated.go
🚧 Files skipped from review as they are similar to previous changes (20)
- gateway/gateway-controller/cmd/controller/main.go
- platform-api/src/internal/dto/gateway_internal.go
- event-gateway/it/features/websub-webhook-secrets.feature
- platform-api/src/resources/gateway-internal-api.yaml
- platform-api/src/internal/repository/interfaces.go
- gateway/gateway-controller/pkg/controlplane/controlplane_test.go
- platform-api/src/internal/service/gateway_events.go
- platform-api/src/internal/database/schema.postgres.sql
- platform-api/src/internal/model/websub_api_hmac_secret.go
- platform-api/src/internal/repository/websub_api_hmac_secret.go
- platform-api/src/api/manual_types.go
- gateway/gateway-controller/pkg/controlplane/client_integration_test.go
- platform-api/src/internal/handler/gateway_internal.go
- platform-api/src/internal/database/schema.sql
- platform-api/src/resources/openapi.yaml
- platform-api/src/internal/database/schema.sqlite.sql
- gateway/gateway-controller/pkg/utils/api_utils.go
- gateway/gateway-controller/pkg/controlplane/client.go
- platform-api/src/internal/handler/websub_api_hmac_secret.go
- platform-api/src/internal/service/websub_api_hmac_secret.go
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 2
🧹 Nitpick comments (1)
platform-api/src/internal/service/websub_api_hmac_secret_test.go (1)
128-234: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd test coverage for name generation boundary conditions.
The Generate tests cover core functionality well but miss three boundary cases in the name generation logic (from service code):
- Display names that slugify to >63 characters (triggering truncation).
- Display names that slugify to empty strings (triggering fallback to "secret-" + apiHandle).
- Very long apiHandle values where the fallback name itself exceeds 63 characters (triggering second truncation).
These are distinct conditional branches in production code that should have explicit test coverage to prevent bugs in identifier generation.
Suggested test cases
// TestWebSubAPIHmacSecret_Generate_LongDisplayNameTruncated verifies that // display names longer than 63 chars are truncated after slugification. func TestWebSubAPIHmacSecret_Generate_LongDisplayNameTruncated(t *testing.T) { websubRepo := newMockWebSubAPIRepository() withWebSubAPI(websubRepo) hmacRepo := newMockHmacSecretRepo() svc := buildHmacSecretService(t, websubRepo, hmacRepo) longName := strings.Repeat("verylongname-", 10) // >63 chars after slug meta, _, err := svc.Generate("org-uuid", "test-api", longName, "") if err != nil { t.Fatalf("Generate with long name failed: %v", err) } if len(meta.Name) != 63 { t.Errorf("expected name truncated to 63 chars, got %d", len(meta.Name)) } } // TestWebSubAPIHmacSecret_Generate_EmptySlugFallback verifies that // display names that slugify to empty trigger fallback name generation. func TestWebSubAPIHmacSecret_Generate_EmptySlugFallback(t *testing.T) { websubRepo := newMockWebSubAPIRepository() withWebSubAPI(websubRepo) hmacRepo := newMockHmacSecretRepo() svc := buildHmacSecretService(t, websubRepo, hmacRepo) meta, _, err := svc.Generate("org-uuid", "test-api", "!@#$%^", "") if err != nil { t.Fatalf("Generate with special-char-only name failed: %v", err) } if meta.Name != "secret-test-api" { t.Errorf("expected fallback name 'secret-test-api', got %q", meta.Name) } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@platform-api/src/internal/service/websub_api_hmac_secret_test.go` around lines 128 - 234, The test file is missing coverage for three boundary conditions in the name generation logic of the Generate method. Add three new test functions to cover: (1) display names longer than 63 characters that get truncated after slugification by verifying the returned meta.Name length equals 63, (2) display names containing only special characters that slugify to empty strings by verifying the fallback generates a name in the format "secret-{apiHandle}", and (3) very long apiHandle values where the fallback name itself exceeds 63 characters by verifying the truncation occurs on the fallback. Follow the existing test structure in the file (using newMockWebSubAPIRepository, newMockHmacSecretRepo, buildHmacSecretService, and calling svc.Generate) to ensure consistency with the current test patterns.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@platform-api/src/internal/database/schema.sqlserver.sql`:
- Around line 395-405: The FOREIGN KEY constraint on project_uuid in the
mcp_proxies table uses ON DELETE CASCADE, which causes automatic deletion of
mcp_proxy records when a project is deleted. However, the application manages
mcp_proxies cleanup at the application layer and expects the database to prevent
project deletion until dependent records are handled. Change the ON DELETE
CASCADE clause on line 404 (the FOREIGN KEY constraint referencing
projects(uuid)) to ON DELETE NO ACTION to enforce this contract and allow the
application to control the cleanup order.
In `@platform-api/src/internal/server/server.go`:
- Around line 237-241: The current logic derives an HMAC encryption key from
cfg.Auth.JWT.SecretKey even when that secret is empty, which produces a valid
hash and masks the missing-key error. Fix this by adding an additional check to
ensure cfg.Auth.JWT.SecretKey is not empty before performing the sha256 hashing
and hex encoding. Only apply the fallback key derivation when both
hmacEncryptionKey is empty AND cfg.Auth.JWT.SecretKey is non-empty, otherwise
leave hmacEncryptionKey empty so the missing-key validation path is properly
triggered.
---
Nitpick comments:
In `@platform-api/src/internal/service/websub_api_hmac_secret_test.go`:
- Around line 128-234: The test file is missing coverage for three boundary
conditions in the name generation logic of the Generate method. Add three new
test functions to cover: (1) display names longer than 63 characters that get
truncated after slugification by verifying the returned meta.Name length equals
63, (2) display names containing only special characters that slugify to empty
strings by verifying the fallback generates a name in the format
"secret-{apiHandle}", and (3) very long apiHandle values where the fallback name
itself exceeds 63 characters by verifying the truncation occurs on the fallback.
Follow the existing test structure in the file (using
newMockWebSubAPIRepository, newMockHmacSecretRepo, buildHmacSecretService, and
calling svc.Generate) to ensure consistency with the current test patterns.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e215386e-064e-4cd4-9038-4157d14f9c9a
📒 Files selected for processing (37)
.github/workflows/event-gateway-integration-test-postgres.yml.github/workflows/event-gateway-integration-test-sqlserver.ymlevent-gateway/docker-compose.test.postgres.yamlevent-gateway/docker-compose.test.sqlserver.yamlevent-gateway/it/Makefileevent-gateway/it/features/websub-webhook-secrets.featureevent-gateway/it/suite_test.gogateway/gateway-controller/cmd/controller/main.gogateway/gateway-controller/pkg/controlplane/client.gogateway/gateway-controller/pkg/controlplane/client_integration_test.gogateway/gateway-controller/pkg/controlplane/controlplane_test.gogateway/gateway-controller/pkg/storage/gateway-controller-db.postgres.sqlgateway/gateway-controller/pkg/storage/gateway-controller-db.sqlserver.sqlgateway/gateway-controller/pkg/utils/api_utils.goplatform-api/src/api/generated.goplatform-api/src/api/manual_types.goplatform-api/src/api/websub_hmac_secret.goplatform-api/src/config/config.goplatform-api/src/internal/constants/error.goplatform-api/src/internal/database/schema.postgres.sqlplatform-api/src/internal/database/schema.sqlplatform-api/src/internal/database/schema.sqlite.sqlplatform-api/src/internal/database/schema.sqlserver.sqlplatform-api/src/internal/dto/gateway_internal.goplatform-api/src/internal/handler/gateway_internal.goplatform-api/src/internal/handler/websub_api_hmac_secret.goplatform-api/src/internal/integration/cascade_test.goplatform-api/src/internal/integration/lifecycle_test.goplatform-api/src/internal/model/websub_api_hmac_secret.goplatform-api/src/internal/repository/interfaces.goplatform-api/src/internal/repository/websub_api_hmac_secret.goplatform-api/src/internal/server/server.goplatform-api/src/internal/service/gateway_events.goplatform-api/src/internal/service/websub_api_hmac_secret.goplatform-api/src/internal/service/websub_api_hmac_secret_test.goplatform-api/src/resources/gateway-internal-api.yamlplatform-api/src/resources/openapi.yaml
✅ Files skipped from review due to trivial changes (3)
- platform-api/src/api/websub_hmac_secret.go
- platform-api/src/internal/constants/error.go
- platform-api/src/api/generated.go
🚧 Files skipped from review as they are similar to previous changes (20)
- gateway/gateway-controller/cmd/controller/main.go
- platform-api/src/internal/dto/gateway_internal.go
- event-gateway/it/features/websub-webhook-secrets.feature
- platform-api/src/resources/gateway-internal-api.yaml
- platform-api/src/internal/repository/interfaces.go
- gateway/gateway-controller/pkg/controlplane/controlplane_test.go
- platform-api/src/internal/service/gateway_events.go
- platform-api/src/internal/database/schema.postgres.sql
- platform-api/src/internal/model/websub_api_hmac_secret.go
- platform-api/src/internal/repository/websub_api_hmac_secret.go
- platform-api/src/api/manual_types.go
- gateway/gateway-controller/pkg/controlplane/client_integration_test.go
- platform-api/src/internal/handler/gateway_internal.go
- platform-api/src/internal/database/schema.sql
- platform-api/src/resources/openapi.yaml
- platform-api/src/internal/database/schema.sqlite.sql
- gateway/gateway-controller/pkg/utils/api_utils.go
- gateway/gateway-controller/pkg/controlplane/client.go
- platform-api/src/internal/handler/websub_api_hmac_secret.go
- platform-api/src/internal/service/websub_api_hmac_secret.go
🛑 Comments failed to post (2)
platform-api/src/internal/database/schema.sqlserver.sql (1)
395-405: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Align MCP proxy project cleanup with the application-managed contract.
Line 404 uses
ON DELETE CASCADE, but this relationship is expected to block project deletion until the application nullifies or removes dependent MCP proxy rows. UseON DELETE NO ACTIONfor SQL Server to match that contract. Based on learnings,mcp_proxies.project_uuidcleanup is handled at the application layer for this relationship.Proposed fix
- FOREIGN KEY (project_uuid) REFERENCES projects(uuid) ON DELETE CASCADE + FOREIGN KEY (project_uuid) REFERENCES projects(uuid) ON DELETE NO ACTION🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@platform-api/src/internal/database/schema.sqlserver.sql` around lines 395 - 405, The FOREIGN KEY constraint on project_uuid in the mcp_proxies table uses ON DELETE CASCADE, which causes automatic deletion of mcp_proxy records when a project is deleted. However, the application manages mcp_proxies cleanup at the application layer and expects the database to prevent project deletion until dependent records are handled. Change the ON DELETE CASCADE clause on line 404 (the FOREIGN KEY constraint referencing projects(uuid)) to ON DELETE NO ACTION to enforce this contract and allow the application to control the cleanup order.Source: Learnings
platform-api/src/internal/server/server.go (1)
237-241: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Do not derive an active HMAC key from an empty JWT secret.
Line 239 hashes
cfg.Auth.JWT.SecretKeywhenever the subscription-token key is empty. If the JWT secret is also unset, this still produces a non-empty key and enables the service instead of following the constructor’s missing-key path. Keep the fallback only for a non-empty JWT secret.Proposed fix
- hmacEncryptionKey := cfg.Database.SubscriptionTokenEncryptionKey + hmacEncryptionKey := strings.TrimSpace(cfg.Database.SubscriptionTokenEncryptionKey) if hmacEncryptionKey == "" { - h := sha256.Sum256([]byte(cfg.Auth.JWT.SecretKey)) - hmacEncryptionKey = hex.EncodeToString(h[:]) + jwtSecret := strings.TrimSpace(cfg.Auth.JWT.SecretKey) + if jwtSecret != "" { + h := sha256.Sum256([]byte(jwtSecret)) + hmacEncryptionKey = hex.EncodeToString(h[:]) + } }📝 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.hmacEncryptionKey := strings.TrimSpace(cfg.Database.SubscriptionTokenEncryptionKey) if hmacEncryptionKey == "" { jwtSecret := strings.TrimSpace(cfg.Auth.JWT.SecretKey) if jwtSecret != "" { h := sha256.Sum256([]byte(jwtSecret)) hmacEncryptionKey = hex.EncodeToString(h[:]) } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@platform-api/src/internal/server/server.go` around lines 237 - 241, The current logic derives an HMAC encryption key from cfg.Auth.JWT.SecretKey even when that secret is empty, which produces a valid hash and masks the missing-key error. Fix this by adding an additional check to ensure cfg.Auth.JWT.SecretKey is not empty before performing the sha256 hashing and hex encoding. Only apply the fallback key derivation when both hmacEncryptionKey is empty AND cfg.Auth.JWT.SecretKey is non-empty, otherwise leave hmacEncryptionKey empty so the missing-key validation path is properly triggered.
35a4b57 to
9c0812c
Compare
|
@coderabbitai review and approve |
|
✅ Action performedComments resolved. Approval is disabled; enable Review finished.
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/platform-api-pr-check.yml:
- Around line 126-144: The timing calculation in the SQL Server readiness check
is off by one interval. In the success message at line 134 where it echoes "SQL
Server ready after $((i * 5))s", change the calculation from `i * 5` to `(i-1) *
5` because when the check succeeds on iteration i, only (i-1) sleep intervals of
5 seconds each have actually elapsed. The first iteration performs the check
immediately without any prior sleep.
In `@platform-api/src/internal/repository/subscription_repository.go`:
- Around line 55-60: The encryption key precedence change in the keyStr
assignment breaks backward compatibility with existing subscription tokens
encrypted using the legacy AUTH_JWT_SECRET_KEY fallback. Preserve the original
fallback order by keeping cfg.Auth.JWT.SecretKey as the final fallback instead
of inserting cfg.Database.EncryptionKey ahead of it, or implement a decryption
fallback mechanism in the decryptSubscriptionToken function that attempts
decryption with multiple keys in sequence (SubscriptionTokenEncryptionKey, then
EncryptionKey, then SecretKey) to ensure tokens encrypted with any of the
previous key sources remain readable during and after the upgrade.
In `@platform-api/src/internal/server/server.go`:
- Around line 239-241: The code at the empty dbEncryptionKey check
unconditionally derives a fallback encryption key by hashing
cfg.Auth.JWT.SecretKey, which bypasses security validation when the JWT secret
is unset. Add a guard condition to verify that cfg.Auth.JWT.SecretKey is
non-empty before performing the sha256 hash derivation in the fallback block; if
the JWT secret is not present, allow the service initialization to fail closed
rather than creating a key from an unset source.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 8d19a49e-d39b-4642-b923-5a3df91cad6d
📒 Files selected for processing (8)
.github/workflows/platform-api-pr-check.ymlgateway/gateway-controller/pkg/storage/gateway-controller-db.postgres.sqlgateway/gateway-controller/pkg/storage/gateway-controller-db.sqlserver.sqlplatform-api/src/config/config.goplatform-api/src/internal/repository/subscription_repository.goplatform-api/src/internal/server/server.goplatform-api/src/internal/service/websub_api_hmac_secret.goplatform-api/src/internal/utils/subscription_token_crypto.go
✅ Files skipped from review due to trivial changes (1)
- platform-api/src/internal/utils/subscription_token_crypto.go
🚧 Files skipped from review as they are similar to previous changes (4)
- gateway/gateway-controller/pkg/storage/gateway-controller-db.postgres.sql
- gateway/gateway-controller/pkg/storage/gateway-controller-db.sqlserver.sql
- platform-api/src/config/config.go
- platform-api/src/internal/service/websub_api_hmac_secret.go
6202dcd to
3e3db16
Compare
add platform api changes for event gateway hmac secret generation