Skip to content

feat: regenerate API client from OpenAPI spec#21

Closed
github-actions[bot] wants to merge 1 commit into
mainfrom
openapi-client-initial
Closed

feat: regenerate API client from OpenAPI spec#21
github-actions[bot] wants to merge 1 commit into
mainfrom
openapi-client-initial

Conversation

@github-actions

@github-actions github-actions Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Automated regeneration via openapi-python-client from docs/v3/openapi3.yaml on 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/convoy HTTP client from the Convoy OpenAPI spec (via openapi-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 exports Client and AuthenticatedClient only; 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.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 027ea9a. Configure here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 027ea9a. Configure here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Comment thread src/convoy/errors.py
self.content = content

super().__init__(
f"Unexpected status code: {status_code}\n\nResponse content:\n{content.decode(errors='ignore')}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 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.

Fix in Cursor Fix in Web

Reviewed by Cursor Security Reviewer for commit 027ea9a. Configure here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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

@mekilis

mekilis commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

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.

@mekilis mekilis closed this Jul 19, 2026
@mekilis
mekilis deleted the openapi-client-initial branch July 19, 2026 20:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant