Skip to content

Fix team member cannot edit agent#14612

Merged
wangq8 merged 6 commits into
infiniflow:mainfrom
wangq8:bugfix/fix-team-member-cannot-edit-agent
May 7, 2026
Merged

Fix team member cannot edit agent#14612
wangq8 merged 6 commits into
infiniflow:mainfrom
wangq8:bugfix/fix-team-member-cannot-edit-agent

Conversation

@wangq8
Copy link
Copy Markdown
Collaborator

@wangq8 wangq8 commented May 7, 2026

What problem does this PR solve?

Follow on PR: #14602
to fix: team member cannot edit agent.
new behavior: beside delete, everything is allowed for team member.

Type of change

  • Bug Fix (non-breaking change which fixes an issue)

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 7, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Centralizes canvas authorization by adding reusable sync/async wrappers and applying them across multiple agent REST routes, removing inline UserCanvasService access/ownership checks from handlers. (50 words)

Changes

Canvas Authorization Consolidation

Layer / File(s) Summary
Authorization helpers
api/apps/restful_apis/agent_api.py
Adds _require_canvas_access_sync, _require_canvas_access_async, and _require_canvas_owner_sync wrappers that call UserCanvasService.accessible / UserCanvasService.query and return standardized JSON errors on denial.
Canvas service permission change
api/db/services/canvas_service.py
Removes tenant ownership guard in UserCanvasService.get_agent_dsl_with_release that previously raised PermissionError when tenant_id differed from canvas owner.
Apply to async session/create
api/apps/restful_apis/agent_api.py
Applies _require_canvas_access_async to POST /agents/<agent_id>/sessions (create_agent_session).
Component input form
api/apps/restful_apis/agent_api.py
Applies _require_canvas_access_sync to GET /agents/<agent_id>/components/<component_id>/input-form; removes inline owner check.
Component debug
api/apps/restful_apis/agent_api.py
Applies _require_canvas_access_async to POST /agents/<agent_id>/components/<component_id>/debug; removes inline accessible check.
Agent update
api/apps/restful_apis/agent_api.py
Applies _require_canvas_access_async to PUT /agents/<agent_id>; removes inline ownership validation block.
Agent reset
api/apps/restful_apis/agent_api.py
Applies _require_canvas_access_async to POST /agents/<agent_id>/reset; removes inline accessible check.
Agent deletion (owner)
api/apps/restful_apis/agent_api.py
Applies _require_canvas_owner_sync to DELETE /agents/<agent_id>; removes inline ownership validation.
Chat completion runtime path
api/apps/restful_apis/agent_api.py
Removes inline thread_pool_exec(UserCanvasService.accessible, ...) check from non-session runtime path; relies on decorator-level authorization instead.
Tests
test/testcases/test_http_api/test_session_management/test_agent_sessions.py, test/testcases/test_web_api/test_agent_app/test_agents_webhook_unit.py
Updates expected authorization error messages and replaces some direct-handler test paths with decorator-wrapped dummy handlers asserting OPERATING_ERROR on denied access.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client
    participant API as AgentAPI
    participant UCS as UserCanvasService
    Client->>API: HTTP request to agent endpoint
    API->>UCS: authorization check (accessible / query) via decorator
    UCS-->>API: allowed / denied
    alt allowed
        API-->>Client: handler executes (200 / SSE / stream)
    else denied
        API-->>Client: 403 JSON error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

lgtm

Suggested reviewers

  • Magicbook1108

Poem

🐇 I hopped through handlers, neat and quick,
Found scattered gates that made me pick —
One wrapper now, each path aligned,
Canvas guarded, checks combined.
A joyful twitch for code refined.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly addresses the main change: fixing team member permissions to edit agents, which is the core objective of this bug fix PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description follows the template and clearly explains the problem (fixing team member edit restrictions) and indicates a Bug Fix type of change.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@wangq8 wangq8 added the ci Continue Integration label May 7, 2026
@wangq8 wangq8 marked this pull request as ready for review May 7, 2026 03:05
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. 🐖api The modified files are located under directory 'api/apps/sdk' labels May 7, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a 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 (2)
api/apps/restful_apis/agent_api.py (2)

71-85: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add denial logging in the new authorization decorators.

Line 75 and Line 84 return auth failures without any log signal. Since this is a new centralized access-control flow, please log denied attempts (agent_id, tenant_id, endpoint/action) for auditability and incident triage.

As per coding guidelines, **/*.py: Add logging for new flows.

🤖 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 `@api/apps/restful_apis/agent_api.py` around lines 71 - 85, The two
authorization decorators _require_canvas_access_sync and
_require_canvas_owner_sync currently return failure responses without logging;
add denial logging before each return by obtaining agent_id and tenant_id from
kwargs, determine the endpoint/action via func.__name__ (and include
request.path or request.method if request is available), and log a structured
warning/error using a module logger (get logger with
logging.getLogger(__name__)); include agent_id, tenant_id, endpoint/action and a
short reason string, then proceed to return the existing get_json_result with
RetCode.OPERATING_ERROR.

71-77: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make _require_canvas_access_sync async-aware to properly handle async endpoints.

The wrapper function is synchronous but wraps multiple async endpoints (lines 185, 452, 581, 632, 809). When called on an async function, it returns an unawaited coroutine. Since add_tenant_id_to_kwargs (the next decorator in the stack) checks inspect.iscoroutinefunction() on the sync wrapper—not the original endpoint—it fails to detect the coroutine and returns it without awaiting, leaking an unawaited coroutine object.

Suggested fix
 def _require_canvas_access_sync(func):
+    is_coro = inspect.iscoroutinefunction(func)
     `@wraps`(func)
-    def wrapper(*args, **kwargs):
+    async def wrapper(*args, **kwargs):
         if not UserCanvasService.accessible(kwargs.get('agent_id'), kwargs.get('tenant_id')):
             return get_json_result(data=False, message="Make sure you have permission to access the agent.", code=RetCode.OPERATING_ERROR)
-        return func(*args, **kwargs)
+        if is_coro:
+            return await func(*args, **kwargs)
+        return func(*args, **kwargs)
     return wrapper
🤖 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 `@api/apps/restful_apis/agent_api.py` around lines 71 - 77, The decorator
_require_canvas_access_sync must be made async-aware: change its inner wrapper
to async def, keep `@wraps`(func), and inside check
UserCanvasService.accessible(...) as before and then call the wrapped func using
await if the original func is a coroutine (use inspect.iscoroutinefunction(func)
or inspect.isawaitable on the result), otherwise call it synchronously; this
ensures async endpoints wrapped by _require_canvas_access_sync are awaited (so
add_tenant_id_to_kwargs can correctly detect coroutine functions) while
preserving behavior for synchronous handlers.
🤖 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 `@api/apps/restful_apis/agent_api.py`:
- Around line 808-809: The route function agent_chat_completion is currently
decorated with `@_require_canvas_access_sync` which expects kwargs["agent_id"] but
agent_id is parsed from the request body inside agent_chat_completion, causing
valid requests to be rejected; remove the `@_require_canvas_access_sync` decorator
from agent_chat_completion and either (a) perform the access check explicitly
after you parse agent_id from the request body by calling the same access-check
routine (use the underlying check function or method the decorator wraps,
passing the parsed agent_id), or (b) change the route to accept agent_id as a
URL parameter so the decorator can access kwargs["agent_id"]; ensure the chosen
fix calls the same access logic that the decorator enforces (the symbol:
_require_canvas_access_sync) using the parsed agent_id.

---

Outside diff comments:
In `@api/apps/restful_apis/agent_api.py`:
- Around line 71-85: The two authorization decorators
_require_canvas_access_sync and _require_canvas_owner_sync currently return
failure responses without logging; add denial logging before each return by
obtaining agent_id and tenant_id from kwargs, determine the endpoint/action via
func.__name__ (and include request.path or request.method if request is
available), and log a structured warning/error using a module logger (get logger
with logging.getLogger(__name__)); include agent_id, tenant_id, endpoint/action
and a short reason string, then proceed to return the existing get_json_result
with RetCode.OPERATING_ERROR.
- Around line 71-77: The decorator _require_canvas_access_sync must be made
async-aware: change its inner wrapper to async def, keep `@wraps`(func), and
inside check UserCanvasService.accessible(...) as before and then call the
wrapped func using await if the original func is a coroutine (use
inspect.iscoroutinefunction(func) or inspect.isawaitable on the result),
otherwise call it synchronously; this ensures async endpoints wrapped by
_require_canvas_access_sync are awaited (so add_tenant_id_to_kwargs can
correctly detect coroutine functions) while preserving behavior for synchronous
handlers.
🪄 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: 378c4030-1868-4f2c-9ebe-546b56b9b600

📥 Commits

Reviewing files that changed from the base of the PR and between 12f80f1 and cd0ac80.

📒 Files selected for processing (1)
  • api/apps/restful_apis/agent_api.py

Comment thread api/apps/restful_apis/agent_api.py Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented May 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.16%. Comparing base (1d0519d) to head (6d57d50).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #14612   +/-   ##
=======================================
  Coverage   94.16%   94.16%           
=======================================
  Files          10       10           
  Lines         703      703           
  Branches      112      112           
=======================================
  Hits          662      662           
  Misses         25       25           
  Partials       16       16           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a 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)
api/apps/restful_apis/agent_api.py (1)

71-95: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add logging in the new authorization wrappers.

Per the repo's Python guideline to add logging for new flows, the three new decorators silently return a generic JSON error on denial without logging the agent_id/tenant_id, which makes auth failures hard to diagnose in production. Consider logging at warning level when access is rejected.

🪵 Suggested change
 def _require_canvas_access_sync(func):
     `@wraps`(func)
     def wrapper(*args, **kwargs):
-        if not UserCanvasService.accessible(kwargs.get('agent_id'), kwargs.get('tenant_id')):
+        agent_id = kwargs.get('agent_id')
+        tenant_id = kwargs.get('tenant_id')
+        if not UserCanvasService.accessible(agent_id, tenant_id):
+            logging.warning("Canvas access denied: agent_id=%s tenant_id=%s", agent_id, tenant_id)
             return get_json_result(data=False, message="Make sure you have permission to access the agent.", code=RetCode.OPERATING_ERROR)
         return func(*args, **kwargs)
     return wrapper


 def _require_canvas_access_async(func):
     `@wraps`(func)
     async def wrapper(*args, **kwargs):
-        if not UserCanvasService.accessible(kwargs.get('agent_id'), kwargs.get('tenant_id')):
+        agent_id = kwargs.get('agent_id')
+        tenant_id = kwargs.get('tenant_id')
+        if not UserCanvasService.accessible(agent_id, tenant_id):
+            logging.warning("Canvas access denied: agent_id=%s tenant_id=%s", agent_id, tenant_id)
             return get_json_result(data=False, message="Make sure you have permission to access the agent.", code=RetCode.OPERATING_ERROR)
         return await func(*args, **kwargs)
     return wrapper


 def _require_canvas_owner_sync(func):
     `@wraps`(func)
     def wrapper(*args, **kwargs):
-        if not UserCanvasService.query(user_id=kwargs.get('tenant_id'), id=kwargs.get('agent_id')):
+        agent_id = kwargs.get('agent_id')
+        tenant_id = kwargs.get('tenant_id')
+        if not UserCanvasService.query(user_id=tenant_id, id=agent_id):
+            logging.warning("Canvas owner-only operation denied: agent_id=%s tenant_id=%s", agent_id, tenant_id)
             return get_json_result(data=False, message="Only the owner of the agent is authorized for this operation.", code=RetCode.OPERATING_ERROR)
         return func(*args, **kwargs)
     return wrapper

As per coding guidelines: "Add logging for new flows".

🤖 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 `@api/apps/restful_apis/agent_api.py` around lines 71 - 95, The three
decorators (_require_canvas_access_sync, _require_canvas_access_async,
_require_canvas_owner_sync) must log authorization denials before returning the
JSON error; add a warning-level log (using the module logger) in each wrapper
that records the agent_id and tenant_id and a short reason (e.g., "access
denied" for UserCanvasService.accessible failures and "owner required" for
UserCanvasService.query failures) immediately before the get_json_result return,
ensuring the async wrapper logs similarly before awaiting the wrapped function.
🧹 Nitpick comments (1)
api/apps/restful_apis/agent_api.py (1)

71-95: 💤 Low value

Decorators rely on URL/query kwargs containing both agent_id and tenant_id.

Both kwargs.get('agent_id') and kwargs.get('tenant_id') silently fall back to None if either key is missing. accessible(None, None) / query(user_id=None, id=None) will likely just return falsy, producing a generic permission denied message even when the real cause is a misconfigured route or a missing @add_tenant_id_to_kwargs. Consider asserting/raising a 500 (or logging an error) when these are missing so route-misconfiguration regressions are caught loudly rather than masked as 403s.

This is also relevant given Line 808's chat-completion route: previously this decorator was incorrectly applied where agent_id is not a URL kwarg; an explicit guard would have made that bug obvious.

🤖 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 `@api/apps/restful_apis/agent_api.py` around lines 71 - 95, The decorators
_require_canvas_access_sync, _require_canvas_access_async and
_require_canvas_owner_sync should explicitly check for presence of both
'agent_id' and 'tenant_id' in kwargs before calling UserCanvasService; update
each wrapper to if either kwargs.get('agent_id') is None or
kwargs.get('tenant_id') is None then log an error about a misconfigured
route/missing `@add_tenant_id_to_kwargs` and return get_json_result(data=False,
message="Missing route parameters: agent_id or tenant_id (possible misconfigured
route).", code=RetCode.SERVER_ERROR) so missing URL/query args produce a loud
500 rather than a silent permission-denied 403; otherwise proceed with the
existing accessible/query checks (preserve async await in
_require_canvas_access_async).
🤖 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 `@api/apps/restful_apis/agent_api.py`:
- Around line 80-86: The async decorator _require_canvas_access_async calls the
synchronous UserCanvasService.accessible inline and blocks the event loop;
change it to offload that DB call via await
thread_pool_exec(UserCanvasService.accessible, agent_id, tenant_id) (extract
agent_id and tenant_id from kwargs as currently done), check the returned
boolean and return get_json_result(data=False, message="Make sure you have
permission to access the agent.", code=RetCode.OPERATING_ERROR) when false,
otherwise await and return func(*args, **kwargs); keep the decorator name and
wrapper signature the same.

---

Outside diff comments:
In `@api/apps/restful_apis/agent_api.py`:
- Around line 71-95: The three decorators (_require_canvas_access_sync,
_require_canvas_access_async, _require_canvas_owner_sync) must log authorization
denials before returning the JSON error; add a warning-level log (using the
module logger) in each wrapper that records the agent_id and tenant_id and a
short reason (e.g., "access denied" for UserCanvasService.accessible failures
and "owner required" for UserCanvasService.query failures) immediately before
the get_json_result return, ensuring the async wrapper logs similarly before
awaiting the wrapped function.

---

Nitpick comments:
In `@api/apps/restful_apis/agent_api.py`:
- Around line 71-95: The decorators _require_canvas_access_sync,
_require_canvas_access_async and _require_canvas_owner_sync should explicitly
check for presence of both 'agent_id' and 'tenant_id' in kwargs before calling
UserCanvasService; update each wrapper to if either kwargs.get('agent_id') is
None or kwargs.get('tenant_id') is None then log an error about a misconfigured
route/missing `@add_tenant_id_to_kwargs` and return get_json_result(data=False,
message="Missing route parameters: agent_id or tenant_id (possible misconfigured
route).", code=RetCode.SERVER_ERROR) so missing URL/query args produce a loud
500 rather than a silent permission-denied 403; otherwise proceed with the
existing accessible/query checks (preserve async await in
_require_canvas_access_async).
🪄 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: f13f2371-d91d-4f83-bbdf-185c2ea759d7

📥 Commits

Reviewing files that changed from the base of the PR and between cd0ac80 and 0b6dc88.

📒 Files selected for processing (1)
  • api/apps/restful_apis/agent_api.py

Comment thread api/apps/restful_apis/agent_api.py
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
test/testcases/test_http_api/test_session_management/test_agent_sessions.py (1)

83-115: 🏗️ Heavy lift

No positive test for the core bug fix (team member editing an existing agent).

The test only exercises error-path contracts on a non-existent "invalid-agent-id". The actual scenario fixed by this PR — a team member successfully editing an existing agent they don't own — is not covered anywhere in this file. Similarly, the restriction that team members cannot delete is only implied by the message string, not exercised with real team-member credentials against a real agent.

Without a positive-path test using a second HttpApiAuth (team-member credentials) against a valid agent_id, it is possible for the underlying server-side change to be wrong (e.g., still blocking edits, or accidentally allowing deletes) while all updated assertions here still pass.

Consider adding a dedicated test (or a separate class TestTeamMemberAgentAccess) with:

  • PUT /agents/{real_agent_id} as a team member → expect success (code == 0)
  • DELETE /agents/{real_agent_id} as a team member → expect failure (code == 103)
🤖 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 `@test/testcases/test_http_api/test_session_management/test_agent_sessions.py`
around lines 83 - 115, Add a positive-path test to cover team-member
edits/deletes: create a new test (e.g., in TestAgentSessions or a new
TestTeamMemberAgentAccess) that uses a second HttpApiAuth representing a
team-member user (distinct from the owner HttpApiAuth) and the real agent_id
fixture; perform a PUT to /api/{VERSION}/agents/{agent_id} with updated payload
and assert res["code"] == 0 (edit allowed), then perform DELETE via
delete_agent(teamMemberHttpApiAuth, agent_id) and assert res["code"] == 103 with
the appropriate message (delete forbidden). Ensure the test references
HttpApiAuth/teamMemberHttpApiAuth, agent_id, the PUT helper or direct
requests.put, and delete_agent so reviewers can locate the new assertions.
🤖 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.

Nitpick comments:
In `@test/testcases/test_http_api/test_session_management/test_agent_sessions.py`:
- Around line 83-115: Add a positive-path test to cover team-member
edits/deletes: create a new test (e.g., in TestAgentSessions or a new
TestTeamMemberAgentAccess) that uses a second HttpApiAuth representing a
team-member user (distinct from the owner HttpApiAuth) and the real agent_id
fixture; perform a PUT to /api/{VERSION}/agents/{agent_id} with updated payload
and assert res["code"] == 0 (edit allowed), then perform DELETE via
delete_agent(teamMemberHttpApiAuth, agent_id) and assert res["code"] == 103 with
the appropriate message (delete forbidden). Ensure the test references
HttpApiAuth/teamMemberHttpApiAuth, agent_id, the PUT helper or direct
requests.put, and delete_agent so reviewers can locate the new assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dcbc9ecb-8e2b-4655-ad17-ad0d6d656ada

📥 Commits

Reviewing files that changed from the base of the PR and between 0b6dc88 and 425ced0.

📒 Files selected for processing (1)
  • test/testcases/test_http_api/test_session_management/test_agent_sessions.py

wangq8 added 3 commits May 7, 2026 13:22
The inline permission checks in update_agent and delete_agent were moved
to decorators (@_require_canvas_access_async, @_require_canvas_owner_sync)
in a previous commit. The tests were still using __wrapped__ to bypass
decorators, so patching UserCanvasService.query had no effect.

Update the tests to:
- Patch UserCanvasService.accessible instead of query for update_agent
- Test decorators directly via dummy functions instead of __wrapped__
- Use _require_canvas_owner_sync dummy for delete_agent permission test
@wangq8 wangq8 requested review from Magicbook1108 and buua436 May 7, 2026 07:00
@wangq8 wangq8 merged commit c50028b into infiniflow:main May 7, 2026
2 checks passed
@dosubot dosubot Bot mentioned this pull request May 9, 2026
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐖api The modified files are located under directory 'api/apps/sdk' ci Continue Integration size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant