Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.

fix(security): scope MCP tool results to caller's meetings, fix AgendaController chair check#327

Merged
rubenvdlinde merged 1 commit into
developmentfrom
fix/mcp-scoping-agenda-auth-306-307
May 27, 2026
Merged

fix(security): scope MCP tool results to caller's meetings, fix AgendaController chair check#327
rubenvdlinde merged 1 commit into
developmentfrom
fix/mcp-scoping-agenda-auth-306-307

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Summary

  • AgendaController (#307): requireChairOrAdmin() checked $pData['owner'] but the participant schema now stores the Nextcloud UID in nextcloudUserId (added in fix: correct OR ObjectService API, add Meeting.chair + Participant.nextcloudUserId, HMAC-sign mail votes #323). Updated to match on nextcloudUserId with a fallback to the legacy owner field for pre-migration records.
  • DecideskToolProvider (#306):
    • listOpenActionItems with scope=all: added post-filter — non-admin callers receive only action items linked to meetings they participate in. Admins are unrestricted.
    • listRecentMeetings: added post-filter — non-admin callers receive only meetings where they have a participant record. Admins are unrestricted.
    • New private helper getCallerMeetingUuids() resolves meeting UUIDs from the caller's participant records and fails closed (returns empty set) if OpenRegister is unavailable.

Test plan

  • Chair user (non-admin) calls PUT /api/agendas/{id}/publish → 200 (was 403)
  • Non-chair non-admin user calls PUT /api/agendas/{id}/publish → 403
  • MCP listRecentMeetings as non-admin → only returns meetings where caller has a participant record
  • MCP listOpenActionItems with scope=all as non-admin → only returns items from caller's meetings
  • Both MCP tools as NC admin → returns all records unrestricted

Fixes #306, #307

…aController chair check

- AgendaController::requireChairOrAdmin: check nextcloudUserId field (PR #323) for chair/secretary role match, with fallback to legacy owner field
- DecideskToolProvider::listOpenActionItems (scope=all): post-filter to action items linked to meetings the caller participates in; admins unfiltered
- DecideskToolProvider::listRecentMeetings: post-filter to meetings the caller participates in via getCallerMeetingUuids helper; admins unfiltered

Fixes #306, #307
@rubenvdlinde rubenvdlinde merged commit 0fc3680 into development May 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant