mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-07 14:26:47 +02:00
* fix(agents): make agent access owner-only editable, read-only for others (MUL-3963) Interaction bug: a non-owner (incl. workspace admin) could open the AccessPicker and set an agent public — the backend silently ignored it and the UI bounced back to private. Access is owner-only, so non-owners must see a read-only state and the backend must reject real changes explicitly. Frontend: - AccessPicker renders a static, non-interactive read-only state when the viewer is not the owner: the current access value + a lock affordance + a tooltip "Only the agent owner can change who can run this agent." No clickable trigger is rendered, so a non-owner can never open a control the backend would reject (the GitHub/Notion pattern for permission settings you can see but not edit). The editable multi-select picker is unchanged for the owner. - agent-detail-inspector gates the picker on ownership specifically (currentUserId === agent.owner_id), NOT the general canEdit (which also admits admins, who may edit other fields but not access). - New locale key access.owner_only_readonly (en/zh-Hans/ja/ko). Backend: - UpdateAgent now returns an explicit 403 when a non-owner submits a REAL permission change (permissionInputChangesAgent compares requested mode + target set against the persisted state); a no-op resubmit (admin PATCH-as-PUT echoing unchanged permission) is still tolerated so admin edits of other fields keep working. Replaces the previous silent-drop that caused the bounce. Tests: - access-picker.test.tsx: non-owner gets a non-interactive read-only display with the owner-only tooltip; owner gets an interactive picker; owner can pick a member and stack workspace + member. - TestUpdateAgent_AccessChangeIsOwnerOnly: admin real change → 403; admin no-op resubmit → 200; admin editing other fields → 200; owner change → 200. Incidental: fixed a pre-existing base typecheck break in slash-command-suggestion.test.tsx (stray `signal` arg not in the suggestion items type) that otherwise fails the whole @multica/views typecheck. Refs MUL-3963. Co-authored-by: multica-agent <github@multica.ai> * fix(agents): compare legacy visibility, not expanded permission, for no-op detection (MUL-3963) PR #4853 review: permissionInputChangesAgent expanded a legacy-only visibility:"private" into a real private permission and compared it against the agent's actual permission. A member-only public_to agent derives legacy visibility "private", so an admin PATCH-as-PUT echoing visibility:"private" while editing another field was misread as a public_to→private downgrade and rejected with 403 — contradicting the "unchanged permission no-op is allowed" contract. Fix (per review): when a request carries ONLY legacy `visibility` (no permission_mode / invocation_targets), derive the agent's CURRENT legacy visibility from its real targets and compare the legacy string values. Equal = no-op (allowed); a real legacy change (e.g. "workspace") still returns 403. Requests that carry permission_mode / invocation_targets keep the precise mode+target comparison. Regression test TestUpdateAgent_LegacyVisibilityNoOpForMemberOnlyPublicTo: member-only public_to agent — admin submitting visibility:"private" + a non-permission field → 200 with targets unchanged; admin submitting visibility:"workspace" → 403. Go handler/composio suites green; migration 130 applied; go vet clean. Refs MUL-3963. Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: multica-agent <github@multica.ai>