feat: regenerate API client from OpenAPI spec#21
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 027ea9a. Configure here.
| acknowledged_at: str | Unset = UNSET | ||
| app_id: str | Unset = UNSET | ||
| created_at: str | Unset = UNSET | ||
| data: list[int] | Unset = UNSET |
There was a problem hiding this comment.
Event data typed as byte array
High Severity
Event payload fields are modeled as list[int] even though the docstring describes arbitrary JSON and the live API returns a JSON object (or other JSON value). This comes from Go json.RawMessage ([]byte) leaking into the OpenAPI schema as an integer array, so fetched event data is mistyped across event and delivery metadata models.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 027ea9a. Configure here.
There was a problem hiding this comment.
Valid, and the root cause is the OpenAPI spec, not the generator: Go's json.RawMessage leaks into swagger as an integer array. Fixed upstream in frain-dev/convoy#2736 (swaggertype:"object" on event data, metadata data, and json_schema; service_account documented as base64 string). This PR will be regenerated from the corrected spec once that merges.
| if response.status_code == 201: | ||
| response_201 = HandlersStub.from_dict(response.json()) | ||
|
|
||
| return response_201 |
There was a problem hiding this comment.
Dynamic event success loses envelope
Medium Severity
A successful 201 from create_dynamic_event is parsed as bare HandlersStub, not a normal response envelope with message, status, and data. Error statuses use structured types, and sibling create-event helpers return proper *Response201 models, so the happy path is inconsistently untyped.
Reviewed by Cursor Bugbot for commit 027ea9a. Configure here.
There was a problem hiding this comment.
Valid, same root cause: CreateDynamicEvent's @success annotation documented a bare Stub while the handler renders util.NewServerResponse(...). Fixed in frain-dev/convoy#2736; regeneration will pick up the enveloped 201.
| self.content = content | ||
|
|
||
| super().__init__( | ||
| f"Unexpected status code: {status_code}\n\nResponse content:\n{content.decode(errors='ignore')}" |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: MEDIUM
UnexpectedStatus embeds the full raw response body in the exception message. In many deployments, uncaught exceptions are shipped to centralized logs, so this change can unintentionally persist sensitive response content.
Impact: Response bodies containing secrets, tokens, or personal data can leak into logging systems and be exposed to broader audiences than the original API caller.
Reviewed by Cursor Security Reviewer for commit 027ea9a. Configure here.
There was a problem hiding this comment.
This is upstream openapi-python-client behavior: UnexpectedStatus is only raised when the caller opts in via raise_on_unexpected_status=True (default False), and the content it carries is the server's response to the caller's own request, not another tenant's data. Whether that exception reaches centralized logs is the consuming application's logging policy. Keeping as by-design; we don't hand-patch generated files (the sync script mirrors generator output).
|
Superseded by #22, regenerated from the corrected spec (frain-dev/convoy#2736): event data is now a JSON object type instead of list[int], and CreateDynamicEvent's 201 is enveloped. Both Bugbot findings resolve there. |


Automated regeneration via openapi-python-client from
docs/v3/openapi3.yamlon frain-dev/convoy main. Hand-written webhook verify (src/convoy/utils/) is untouched by the sync script.Note
Low Risk
Large generated-only diff with no runtime logic changes in hand-maintained code; main risk is API contract drift vs the OpenAPI spec, not production service behavior.
Overview
Regenerates the
src/convoyHTTP client from the Convoy OpenAPI spec (viaopenapi-python-client), replacing or introducing the generated surface that talks to/v1/projects/...with httpx and typed request/response models.The update adds or refreshes sync and async call helpers across major API areas—endpoints (CRUD, activate/pause, secret rotation, OAuth2 test), event types, events (broadcast, dynamic, batch replay and counts), event deliveries (list/get, resend, batch retry, force resend), and delivery attempts—each following the same generated pattern (
sync/sync_detailed/asyncio/asyncio_detailed). The package root still exportsClientandAuthenticatedClientonly;src/convoy/utils/(hand-written webhook verification) is outside this regeneration path.Reviewed by Cursor Bugbot for commit 027ea9a. Bugbot is set up for automated code reviews on this repo. Configure here.