-
Notifications
You must be signed in to change notification settings - Fork 201
feat: add pagination and limit handling for API keys #2430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: add pagination and limit handling for API keys #2430
Conversation
WalkthroughAdds pagination (limit/offset) and total-count fields to protobufs and handlers, replaces hard-limit errors with clamped defaults across many server endpoints, adds API-key creation pre-check (200 limit), updates repository queries for pagination/count, and enables client-side pagination in the API keys UI. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used🧬 Code graph analysis (1)controlplane/src/core/bufservices/api-key/getAPIKeys.ts (1)
⏰ 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). (15)
🔇 Additional comments (2)
Comment |
Codecov Report❌ Patch coverage is ❌ Your patch check has failed because the patch coverage (23.78%) is below the target coverage (90.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #2430 +/- ##
===========================================
- Coverage 61.35% 35.94% -25.42%
===========================================
Files 229 943 +714
Lines 23814 123006 +99192
Branches 0 4879 +4879
===========================================
+ Hits 14612 44210 +29598
- Misses 7970 77258 +69288
- Partials 1232 1538 +306
🚀 New features to boost your workflow:
|
Router-nonroot image scan passed✅ No security vulnerabilities found in image: |
There was a problem hiding this 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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
controlplane/src/core/bufservices/check/getChecksByFederatedGraphName.ts (1)
73-85: Add validation for lower bounds of limit and offset.The code validates that
limit <= 50but doesn't check iflimitis at least 1, nor does it validate thatoffset >= 0. Negative or zero limit values could bypass intended constraints; negative offset values could cause unexpected database behavior.
🧹 Nitpick comments (6)
controlplane/src/core/bufservices/organization/getAuditLogs.ts (1)
57-58: Consider using nullish coalescing operator.The logical OR (
||) operator treats all falsy values (including0) as missing. While unlikely to cause issues in this context, the nullish coalescing operator (??) is generally preferred for defaulting, as it only treatsundefinedandnullas missing values.🔎 Proposed refactor
-req.limit = req.limit || 50; +req.limit = req.limit ?? 50;controlplane/src/core/bufservices/check/getCheckOperations.ts (2)
76-77: Default limit handling looks good.The logic correctly sets a default limit of 200 when not provided, preventing the validation error on line 79 from triggering unexpectedly.
Optional: Consider using nullish coalescing and a local variable
The
||operator will treat explicit0as falsy and override it to 200. While this is unlikely to be a practical issue (0 doesn't make sense for pagination), the nullish coalescing operator (??) would be more precise. Additionally, using a local variable avoids mutating the request object:- req.limit = req.limit || 200; + const limit = req.limit ?? 200;Then update the validation and usage:
- if (req.limit > 200) { + if (limit > 200) {And at line 97:
- limit: req.limit, + limit: limit,
79-93: Consider improving the error message clarity.The validation logic is correct, but the error message "Invalid limit" could be more descriptive to help API consumers understand the constraint.
Optional: More descriptive error message
- details: 'Invalid limit', + details: 'Limit must not exceed 200',controlplane/src/core/bufservices/api-key/getAPIKeys.ts (1)
22-32: Pagination validation implemented correctly.The defaulting and validation logic is sound. The function correctly defaults
limitto 50 and validates it doesn't exceed 50.Optional: Add validation for negative or zero limits
While the current defaulting prevents negative limits in practice, you could add an explicit check for completeness:
req.limit = req.limit || 50; -if (req.limit > 50) { +if (req.limit <= 0 || req.limit > 50) { return { response: { code: EnumStatusCode.ERR, details: 'Invalid limit', }, apiKeys: [], count: 0, }; }studio/src/pages/[organizationSlug]/apikeys.tsx (2)
714-725: Pagination query setup implemented correctly.The page number and limit extraction from router query is well-implemented, with appropriate defaults and client-side limit capping.
Optional: Specify radix in parseInt
For clarity and to avoid edge cases, consider explicitly specifying the radix:
-const pageNumber = router.query.page ? parseInt(router.query.page as string) : 1; +const pageNumber = router.query.page ? parseInt(router.query.page as string, 10) : 1;
769-769: Consider handling empty non-first pages.The condition
apiKeys.length === 0 && pageNumber === 1correctly shows the empty state only on the first page. However, if a user navigates to a page that becomes empty (e.g., after deletion), they'll see an empty table rather than being redirected to a valid page.This is acceptable current behavior, but you could enhance UX by redirecting to the last valid page when the current page is empty and
pageNumber > 1:useEffect(() => { if (apiKeys.length === 0 && pageNumber > 1 && noOfPages > 0) { router.push({ pathname: router.pathname, query: { ...router.query, page: noOfPages }, }); } }, [apiKeys.length, pageNumber, noOfPages, router]);
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
connect-go/gen/proto/wg/cosmo/platform/v1/platform.pb.gois excluded by!**/*.pb.go,!**/gen/**
📒 Files selected for processing (12)
connect/src/wg/cosmo/platform/v1/platform_pb.tscontrolplane/src/core/bufservices/api-key/createAPIKey.tscontrolplane/src/core/bufservices/api-key/getAPIKeys.tscontrolplane/src/core/bufservices/check/getCheckOperations.tscontrolplane/src/core/bufservices/check/getChecksByFederatedGraphName.tscontrolplane/src/core/bufservices/federated-graph/getCompositions.tscontrolplane/src/core/bufservices/organization/getAuditLogs.tscontrolplane/src/core/bufservices/proposal/getProposalChecks.tscontrolplane/src/core/bufservices/proposal/getProposalsByFederatedGraph.tscontrolplane/src/core/repositories/ApiKeyRepository.tsproto/wg/cosmo/platform/v1/platform.protostudio/src/pages/[organizationSlug]/apikeys.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-10T11:15:52.157Z
Learnt from: JivusAyrus
Repo: wundergraph/cosmo PR: 2156
File: controlplane/src/core/repositories/ProposalRepository.ts:562-572
Timestamp: 2025-09-10T11:15:52.157Z
Learning: The getLatestCheckForProposal function in controlplane/src/core/repositories/ProposalRepository.ts is only called during proposal creation or updates, so proposal match error checking (hasProposalMatchError) is not needed since the proposal is being modified itself rather than being matched against.
Applied to files:
controlplane/src/core/bufservices/proposal/getProposalChecks.ts
🧬 Code graph analysis (3)
controlplane/src/core/repositories/ApiKeyRepository.ts (4)
controlplane/src/types/index.ts (1)
APIKeyDTO(317-326)controlplane/src/db/schema.ts (1)
apiKeys(1175-1205)controlplane/src/core/repositories/SubgraphRepository.ts (1)
count(818-853)controlplane/src/core/repositories/FederatedGraphRepository.ts (1)
count(557-572)
controlplane/src/core/bufservices/api-key/getAPIKeys.ts (1)
controlplane/src/db/schema.ts (1)
apiKeys(1175-1205)
studio/src/pages/[organizationSlug]/apikeys.tsx (7)
studio/src/components/group-select.tsx (1)
GroupSelect(8-70)controlplane/src/core/bufservices/api-key/getAPIKeys.ts (1)
getAPIKeys(9-52)controlplane/src/core/repositories/ApiKeyRepository.ts (1)
getAPIKeys(111-153)controlplane/src/core/util.ts (1)
checkUserAccess(284-291)controlplane/src/db/schema.ts (1)
apiKeys(1175-1205)connect/src/wg/cosmo/platform/v1/platform_pb.ts (1)
Pagination(5857-5895)connect-go/gen/proto/wg/cosmo/platform/v1/platform.pb.go (3)
Pagination(7076-7083)Pagination(7098-7098)Pagination(7113-7115)
⏰ 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). (15)
- GitHub Check: build-router
- GitHub Check: build_test
- GitHub Check: build_push_image
- GitHub Check: build_test
- GitHub Check: integration_test (./telemetry)
- GitHub Check: build_push_image
- GitHub Check: integration_test (./. ./fuzzquery ./lifecycle ./modules)
- GitHub Check: build_test
- GitHub Check: integration_test (./events)
- GitHub Check: image_scan
- GitHub Check: image_scan (nonroot)
- GitHub Check: build_push_image (nonroot)
- GitHub Check: build_push_image
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: Analyze (go)
🔇 Additional comments (13)
controlplane/src/core/bufservices/organization/getAuditLogs.ts (1)
57-69: LGTM! Default limit and validation implemented correctly.The implementation properly defaults the limit to 50 when not provided and enforces the maximum bound, which aligns with the PR's DOS prevention objectives.
controlplane/src/core/bufservices/proposal/getProposalsByFederatedGraph.ts (2)
98-99: LGTM: Default limit handling.The default limit of 50 is correctly applied before validation, ensuring consistent pagination behavior when no limit is specified.
112-159: Include totalProposalsCount in the pagination response.The
getProposalCheckshandler returnstotalChecksCountfor pagination support, butgetProposalsByFederatedGraphomits a total count despite supporting paginated requests (limit/offset). TheProposalRepository.countByFederatedGraphIdmethod exists and is used elsewhere (createProposal), so it should be called here to match pagination patterns across handlers and support client-side pagination calculations.controlplane/src/core/bufservices/proposal/getProposalChecks.ts (2)
78-79: LGTM: Consistent default limit handling.The default limit of 50 is correctly applied before validation, maintaining consistency with the pagination pattern used in
getProposalsByFederatedGraph.
103-109: Good: Complete pagination response.The response correctly includes
totalChecksCountalongside the paginated results, enabling proper client-side pagination controls.controlplane/src/core/bufservices/federated-graph/getCompositions.ts (1)
74-75: LGTM! Pagination defaults and validation added.The defaulting of
limitto 50 and the upper-bound validation are correctly implemented and consistent with the pagination pattern used throughout this PR.proto/wg/cosmo/platform/v1/platform.proto (1)
1091-1099: LGTM! Pagination fields added to API Keys messages.The protobuf definitions correctly add
limitandoffsetto the request andcountto the response, following standard pagination patterns.controlplane/src/core/bufservices/api-key/createAPIKey.ts (1)
34-47: LGTM! API key limit enforcement added.The pre-check correctly enforces a maximum of 200 API keys per organization, addressing the DoS risk mentioned in the PR objectives. The
>= 200check allows exactly 200 keys to be created while preventing the 201st, which is the intended behavior.controlplane/src/core/bufservices/api-key/getAPIKeys.ts (1)
34-42: LGTM! Pagination implementation complete.The function correctly fetches paginated API keys and the total count, returning both in the response as defined in the protobuf schema.
controlplane/src/core/repositories/ApiKeyRepository.ts (1)
155-165: LGTM! Total count method implemented correctly.The
getAPIKeysCountmethod is well-implemented, using the standard pattern of querying withcount()and providing a sensible fallback.studio/src/pages/[organizationSlug]/apikeys.tsx (2)
765-765: LGTM! Page count calculation is correct.The calculation properly uses
Math.ceilto handle partial pages and includes a fallback for undefined count.
931-935: LGTM! Pagination component integrated correctly.The Pagination component is properly configured with the necessary props for page navigation.
connect/src/wg/cosmo/platform/v1/platform_pb.ts (1)
8175-8183: Generated code looks correct for pagination support.This is auto-generated protobuf code, and the pagination fields (
limit,offseton request;counton response) are correctly defined. The default value of0forlimitmeans the service layer must handle this case by applying a sensible default limit to prevent unbounded queries.Ensure the corresponding service implementation validates that
limit > 0(or applies a default) and thatoffset >= 0before executing database queries.Also applies to: 8228-8231
wilsonrivera
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we clamp the limits instead of returning a failure? That way we can prevent negative values too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Nitpick comments (1)
controlplane/src/core/bufservices/api-key/getAPIKeys.ts (1)
25-33: Consider concurrent execution of queries.The API keys fetch and count query execute sequentially. For better performance, consider running them concurrently using
Promise.all.🔎 Proposed optimization
- const apiKeys = await apiKeyRepo.getAPIKeys({ - organizationID: authContext.organizationId, - limit: req.limit, - offset: req.offset, - }); - - const count = await apiKeyRepo.getAPIKeysCount({ - organizationID: authContext.organizationId, - }); + const [apiKeys, count] = await Promise.all([ + apiKeyRepo.getAPIKeys({ + organizationID: authContext.organizationId, + limit: req.limit, + offset: req.offset, + }), + apiKeyRepo.getAPIKeysCount({ + organizationID: authContext.organizationId, + }), + ]);
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
controlplane/src/core/bufservices/api-key/getAPIKeys.tscontrolplane/src/core/bufservices/check/getCheckOperations.tscontrolplane/src/core/bufservices/check/getChecksByFederatedGraphName.tscontrolplane/src/core/bufservices/federated-graph/getCompositions.tscontrolplane/src/core/bufservices/organization/getAuditLogs.tscontrolplane/src/core/bufservices/proposal/getProposalChecks.tscontrolplane/src/core/bufservices/proposal/getProposalsByFederatedGraph.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- controlplane/src/core/bufservices/federated-graph/getCompositions.ts
- controlplane/src/core/bufservices/check/getChecksByFederatedGraphName.ts
- controlplane/src/core/bufservices/check/getCheckOperations.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-10T11:15:52.157Z
Learnt from: JivusAyrus
Repo: wundergraph/cosmo PR: 2156
File: controlplane/src/core/repositories/ProposalRepository.ts:562-572
Timestamp: 2025-09-10T11:15:52.157Z
Learning: The getLatestCheckForProposal function in controlplane/src/core/repositories/ProposalRepository.ts is only called during proposal creation or updates, so proposal match error checking (hasProposalMatchError) is not needed since the proposal is being modified itself rather than being matched against.
Applied to files:
controlplane/src/core/bufservices/proposal/getProposalChecks.tscontrolplane/src/core/bufservices/proposal/getProposalsByFederatedGraph.ts
📚 Learning: 2025-08-29T10:28:04.846Z
Learnt from: JivusAyrus
Repo: wundergraph/cosmo PR: 2156
File: controlplane/src/core/repositories/SubgraphRepository.ts:1749-1751
Timestamp: 2025-08-29T10:28:04.846Z
Learning: In the controlplane codebase, authentication and authorization checks (including organization scoping) are handled at the service layer in files like unlinkSubgraph.ts before calling repository methods. Repository methods like unlinkSubgraph() in SubgraphRepository.ts can focus purely on data operations without redundant security checks.
Applied to files:
controlplane/src/core/bufservices/proposal/getProposalChecks.tscontrolplane/src/core/bufservices/proposal/getProposalsByFederatedGraph.ts
🧬 Code graph analysis (3)
controlplane/src/core/bufservices/proposal/getProposalChecks.ts (1)
controlplane/src/core/util.ts (1)
clamp(543-545)
controlplane/src/core/bufservices/api-key/getAPIKeys.ts (1)
controlplane/src/db/schema.ts (1)
apiKeys(1175-1205)
controlplane/src/core/bufservices/proposal/getProposalsByFederatedGraph.ts (1)
controlplane/src/core/util.ts (1)
clamp(543-545)
⏰ 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). (15)
- GitHub Check: build-router
- GitHub Check: build_test
- GitHub Check: integration_test (./events)
- GitHub Check: build_push_image (nonroot)
- GitHub Check: build_push_image
- GitHub Check: integration_test (./. ./fuzzquery ./lifecycle ./modules)
- GitHub Check: integration_test (./telemetry)
- GitHub Check: build_test
- GitHub Check: image_scan (nonroot)
- GitHub Check: build_push_image
- GitHub Check: image_scan
- GitHub Check: build_push_image
- GitHub Check: build_test
- GitHub Check: Analyze (go)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (6)
controlplane/src/core/bufservices/organization/getAuditLogs.ts (1)
12-12: LGTM! Unified limit handling.The addition of the
clamputility import aligns with the PR objective to standardize limit handling across services.controlplane/src/core/bufservices/proposal/getProposalsByFederatedGraph.ts (1)
12-12: LGTM! Import addition supports new pagination logic.The
clampimport is correctly added to support the limit handling introduced on line 99.controlplane/src/core/bufservices/proposal/getProposalChecks.ts (1)
11-11: LGTM! Import is necessary for the clamping logic.The addition of the
clampimport is correct and required for the limit handling introduced on line 79.controlplane/src/core/bufservices/api-key/getAPIKeys.ts (3)
7-7: LGTM: Import added for clamp utility.The
clampfunction import is correctly added to support the new limit validation logic.
23-23: LGTM: Limit clamping logic is correct.The clamp implementation correctly defaults to 10 when no limit is provided and constrains the value between 1 and 50, preventing both empty results and excessive queries.
35-41: LGTM: Response structure correctly includes count.The response properly returns both the paginated API keys and the total count, enabling proper pagination UI implementation.
controlplane/src/core/bufservices/proposal/getProposalChecks.ts
Outdated
Show resolved
Hide resolved
controlplane/src/core/bufservices/proposal/getProposalsByFederatedGraph.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
controlplane/src/core/bufservices/organization/getAuditLogs.ts (1)
12-12: DoS prevention logic is sound; consider the mutation pattern.The clamp-based limit handling effectively prevents DoS by defaulting to 10 and constraining to [1, 50]. The typo mentioned in the past review has been corrected.
However, the pattern of mutating
req.limitdirectly (rather than using a local variable) persists. While this works in the current context, it could have unintended side effects if the request object is reused elsewhere. This pattern is consistent across the PR, so if you choose to refactor, consider applying the change uniformly.📝 Example refactor using a local variable
- // default to 10 if no limit is provided - req.limit = clamp(req.limit || 10, 1, 50); + // default to 10 if no limit is provided + const limit = clamp(req.limit || 10, 1, 50); const auditLogs = await auditLogRepo.getAuditLogs({ organizationId: authContext.organizationId, - limit: req.limit, + limit, offset: req.offset,Also applies to: 57-58
controlplane/src/core/bufservices/federated-graph/getCompositions.ts (1)
13-13: Consistent and effective limit handling.The clamp implementation correctly prevents DoS by defaulting to 10 and bounding to [1, 50]. The logic is sound and consistent with the pagination pattern across the PR.
As with
getAuditLogs.ts, consider using a local variable instead of mutatingreq.limitdirectly to avoid potential side effects if the request object is reused.📝 Example refactor using a local variable
- // default to 10 if no limit is provided - req.limit = clamp(req.limit || 10, 1, 50); + // default to 10 if no limit is provided + const limit = clamp(req.limit || 10, 1, 50); const compositions = await graphCompositionRepository.getGraphCompositions({ fedGraphTargetId: federatedGraph.targetId, organizationId: authContext.organizationId, - limit: req.limit, + limit, offset: req.offset,Also applies to: 74-75
controlplane/src/core/bufservices/check/getCheckOperations.ts (1)
13-13: Effective limit handling with appropriate bounds for operations.The clamp implementation correctly prevents DoS by defaulting to 10 and bounding to [1, 200]. The higher maximum limit (200 vs. 50 in audit logs and compositions) is appropriate given that check operations typically involve larger datasets.
As with the other pagination handlers, consider using a local variable instead of mutating
req.limitdirectly to maintain request object immutability.📝 Example refactor using a local variable
- // default to 10 if no limit is provided - req.limit = clamp(req.limit || 10, 1, 200); + // default to 10 if no limit is provided + const limit = clamp(req.limit || 10, 1, 200); const affectedOperations = await schemaCheckRepo.getAffectedOperationsByCheckId({ checkId: req.checkId, - limit: req.limit, + limit, offset: req.offset,Also applies to: 76-77
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
controlplane/src/core/bufservices/api-key/getAPIKeys.tscontrolplane/src/core/bufservices/check/getCheckOperations.tscontrolplane/src/core/bufservices/check/getChecksByFederatedGraphName.tscontrolplane/src/core/bufservices/federated-graph/getCompositions.tscontrolplane/src/core/bufservices/organization/getAuditLogs.tscontrolplane/src/core/bufservices/proposal/getProposalChecks.tscontrolplane/src/core/bufservices/proposal/getProposalsByFederatedGraph.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- controlplane/src/core/bufservices/proposal/getProposalChecks.ts
- controlplane/src/core/bufservices/api-key/getAPIKeys.ts
- controlplane/src/core/bufservices/proposal/getProposalsByFederatedGraph.ts
- controlplane/src/core/bufservices/check/getChecksByFederatedGraphName.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-19T11:26:26.657Z
Learnt from: JivusAyrus
Repo: wundergraph/cosmo PR: 2331
File: studio/src/components/operations/client-usage-table.tsx:65-65
Timestamp: 2025-11-19T11:26:26.657Z
Learning: In the Cosmo studio codebase (studio/src/components/operations/client-usage-table.tsx), converting BigInt request counts from the API to Number is acceptable because request counts are not expected to exceed JavaScript's safe integer limit (2^53 - 1).
Applied to files:
controlplane/src/core/bufservices/check/getCheckOperations.ts
📚 Learning: 2025-08-29T10:28:04.846Z
Learnt from: JivusAyrus
Repo: wundergraph/cosmo PR: 2156
File: controlplane/src/core/repositories/SubgraphRepository.ts:1749-1751
Timestamp: 2025-08-29T10:28:04.846Z
Learning: In the controlplane codebase, authentication and authorization checks (including organization scoping) are handled at the service layer in files like unlinkSubgraph.ts before calling repository methods. Repository methods like unlinkSubgraph() in SubgraphRepository.ts can focus purely on data operations without redundant security checks.
Applied to files:
controlplane/src/core/bufservices/check/getCheckOperations.ts
🧬 Code graph analysis (1)
controlplane/src/core/bufservices/check/getCheckOperations.ts (1)
controlplane/src/core/util.ts (1)
clamp(543-545)
⏰ 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). (15)
- GitHub Check: build_test
- GitHub Check: build_push_image
- GitHub Check: build-router
- GitHub Check: build_push_image
- GitHub Check: build_push_image
- GitHub Check: build_test
- GitHub Check: build_test
- GitHub Check: integration_test (./. ./fuzzquery ./lifecycle ./modules)
- GitHub Check: image_scan
- GitHub Check: image_scan (nonroot)
- GitHub Check: build_push_image (nonroot)
- GitHub Check: integration_test (./events)
- GitHub Check: integration_test (./telemetry)
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: Analyze (go)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
controlplane/test/fetch-checks-by-federated-graph.test.ts (1)
224-242: Consider publishing an initial schema before running checks.The test creates 51 checks without first publishing a baseline schema to the subgraph. Other tests in this file follow the pattern of publishing a schema first (e.g., lines 73-80, 176-182, 365-379), then running additional checks against that baseline. While
checkSubgraphSchemamay work without a prior publish, adding an initial publish would:
- Ensure consistency with the established test pattern
- Provide a clear baseline for the checks to validate against
- Reduce the risk of unexpected behavior in check recording
🔎 Suggested addition
expect(createSubgraphResp.response?.code).toBe(EnumStatusCode.OK); +// Publish an initial schema to establish a baseline +const initialPublishResp = await client.publishFederatedSubgraph({ + name: subgraphName, + namespace: DEFAULT_NAMESPACE, + schema: 'type Query { initial: String }', +}); + +expect(initialPublishResp.response?.code).toBe(EnumStatusCode.OK); + // Create 51 checks for (let i = 0; i < 51; i++) {
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
controlplane/test/fetch-checks-by-federated-graph.test.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-08T20:57:07.946Z
Learnt from: JivusAyrus
Repo: wundergraph/cosmo PR: 2156
File: controlplane/src/core/repositories/SubgraphRepository.ts:1746-1763
Timestamp: 2025-09-08T20:57:07.946Z
Learning: The checkSubgraphSchema.ts file already correctly implements linked subgraph functionality, using byName(linkedSubgraph.name, linkedSubgraph.namespace) to fetch target subgraphs and properly handles parse(newSchemaSDL) for schema building. The implementation doesn't need fixes for byId usage or schema parsing as it's already correct.
Applied to files:
controlplane/test/fetch-checks-by-federated-graph.test.ts
📚 Learning: 2025-08-29T10:28:04.846Z
Learnt from: JivusAyrus
Repo: wundergraph/cosmo PR: 2156
File: controlplane/src/core/repositories/SubgraphRepository.ts:1749-1751
Timestamp: 2025-08-29T10:28:04.846Z
Learning: In the controlplane codebase, authentication and authorization checks (including organization scoping) are handled at the service layer in files like unlinkSubgraph.ts before calling repository methods. Repository methods like unlinkSubgraph() in SubgraphRepository.ts can focus purely on data operations without redundant security checks.
Applied to files:
controlplane/test/fetch-checks-by-federated-graph.test.ts
🧬 Code graph analysis (1)
controlplane/test/fetch-checks-by-federated-graph.test.ts (2)
controlplane/src/core/test-util.ts (1)
genID(53-55)controlplane/test/test-util.ts (1)
DEFAULT_NAMESPACE(52-52)
⏰ 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). (15)
- GitHub Check: build-router
- GitHub Check: build_push_image
- GitHub Check: build_test
- GitHub Check: integration_test (./. ./fuzzquery ./lifecycle ./modules)
- GitHub Check: build_test
- GitHub Check: build_push_image
- GitHub Check: integration_test (./telemetry)
- GitHub Check: build_push_image (nonroot)
- GitHub Check: integration_test (./events)
- GitHub Check: image_scan
- GitHub Check: image_scan (nonroot)
- GitHub Check: build_push_image
- GitHub Check: build_test
- GitHub Check: Analyze (go)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
controlplane/test/fetch-checks-by-federated-graph.test.ts (2)
234-242: The identical schemas are acceptable for limit testing.All 51 checks use the same schema (
type Query { a: String }). While this is sufficient for testing the limit clamping behavior, varying the schemas slightly (e.g., adding an index to field names) could make the test more representative of real-world usage. However, for the specific purpose of validating pagination limits, the current approach is adequate.
247-278: LGTM! Limit clamping logic is correctly validated.The test properly validates the new limit clamping behavior:
- Limits exceeding 50 are accepted and return a successful response (line 260)
- Results are correctly clamped to 50 items (line 262)
- Valid limit values work as expected (line 278)
This aligns with the PR objective to add pagination and limit handling with clamping instead of hard rejections.
There was a problem hiding this 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
🧹 Nitpick comments (2)
controlplane/src/core/bufservices/api-key/getAPIKeys.ts (1)
27-35: LGTM! Pagination implementation follows standard patterns.The paginated fetch and separate count retrieval are correctly implemented and scoped to the organization. This two-query approach is a common pagination pattern.
Optional consideration: If the count query becomes expensive at scale, consider caching the total count or using database-level optimizations (e.g., indexed count queries). Monitor query performance as the number of API keys grows.
controlplane/src/core/bufservices/federated-graph/getCompositions.ts (1)
74-76: Enhance the comment to document both pagination parameters and clamping bounds.The comment on line 74 only mentions the default limit but doesn't describe the offset default or the clamping ranges for both parameters. Updating it would improve clarity:
- // default to 10 if no limit is provided + // Clamp pagination: limit defaults to 10 [1-50], offset defaults to 0 [0-500000] req.limit = clamp(req.limit || 10, 1, 50); req.offset = clamp(req.offset || 0, 0, 500_000);This pattern is consistent across other pagination handlers in bufservices (getAuditLogs, getProposalChecks, getChecksByFederatedGraphName, etc.), with the offset bound intentionally set to prevent database performance degradation from excessively large offsets.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
controlplane/src/core/bufservices/api-key/getAPIKeys.tscontrolplane/src/core/bufservices/check/getCheckOperations.tscontrolplane/src/core/bufservices/check/getChecksByFederatedGraphName.tscontrolplane/src/core/bufservices/federated-graph/getCompositions.tscontrolplane/src/core/bufservices/organization/getAuditLogs.tscontrolplane/src/core/bufservices/proposal/getProposalChecks.tscontrolplane/src/core/bufservices/proposal/getProposalsByFederatedGraph.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- controlplane/src/core/bufservices/proposal/getProposalsByFederatedGraph.ts
- controlplane/src/core/bufservices/check/getChecksByFederatedGraphName.ts
- controlplane/src/core/bufservices/proposal/getProposalChecks.ts
- controlplane/src/core/bufservices/check/getCheckOperations.ts
⏰ 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). (15)
- GitHub Check: build-router
- GitHub Check: integration_test (./. ./fuzzquery ./lifecycle ./modules)
- GitHub Check: integration_test (./telemetry)
- GitHub Check: build_push_image (nonroot)
- GitHub Check: integration_test (./events)
- GitHub Check: build_push_image
- GitHub Check: build_push_image
- GitHub Check: build_test
- GitHub Check: image_scan
- GitHub Check: image_scan (nonroot)
- GitHub Check: build_test
- GitHub Check: build_push_image
- GitHub Check: build_test
- GitHub Check: Analyze (go)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
controlplane/src/core/bufservices/organization/getAuditLogs.ts (1)
57-59: Good DoS prevention with pagination bounds.The clamping logic correctly prevents DoS attacks by limiting both
limitto [1, 50] andoffsetto [0, 500_000]. The addition of offset clamping (line 59) is a solid improvement.I notice the mutation approach for
req.limitandreq.offsetwas retained despite the previous suggestion to use local variables. Given the earlier feedback that "either approach works", this is fine—just wanted to confirm this was the intended resolution.controlplane/src/core/bufservices/api-key/getAPIKeys.ts (3)
7-7: LGTM! Clamp utility correctly imported.The
clamputility is properly imported and used for enforcing pagination bounds.
22-23: LGTM! Limit validation is correct.The default value of 10 and bounds [1, 50] are sensible for API key pagination.
37-43: LGTM! Response structure correctly includes pagination metadata.The response properly includes both the paginated
apiKeysand thecount, enabling client-side pagination controls.controlplane/src/core/bufservices/federated-graph/getCompositions.ts (1)
13-13: LGTM! Import addition supports the pagination clamping logic.The
clampimport is necessary for the new pagination bounds enforcement on lines 75-76.
Summary by CodeRabbit
New Features
Bug Fixes / Improvements
Tests
✏️ Tip: You can customize this high-level summary in your review settings.
Checklist