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

fix(security): ParticipantResolver — replace five broken participant filters (C3/H1/H2)#335

Merged
rubenvdlinde merged 1 commit into
developmentfrom
fix/pass2-participant-resolver
May 28, 2026
Merged

fix(security): ParticipantResolver — replace five broken participant filters (C3/H1/H2)#335
rubenvdlinde merged 1 commit into
developmentfrom
fix/pass2-participant-resolver

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Summary

  • Introduces ParticipantResolver service with the canonical meeting → governanceBody → participants path (mirrors VotingService::checkQuorum which was the only correct site)
  • Routes all five broken @self.relations.meeting participant-filter sites through it: AgendaController, LiveMeetingController, MinutesController, VotingService (castVote member-check + saveShowOfHandsTally count), DecideskToolProvider::requireParticipantOrAdmin
  • Fixes VotingService preset-validation filter (governanceBodyId: $meetingId → correct governance-body lookup)
  • All chair/secretary access guards now correctly enforce role; previously returned empty participant list → fail-open

Findings fixed

  • C3 Schema↔code mismatch: @self.relations.meeting doesn't exist on participant schema (5 sites)
  • H1 MCP requireParticipantOrAdmin used stale meeting['participants'] array
  • H2 VotingService participant-filter shapes inconsistent (3 shapes unified)

Test plan

  • vendor/bin/phpunit --configuration phpunit-unit.xml --no-coverage passes
  • vendor/bin/phpstan analyse lib/ passes
  • vendor/bin/phpcs lib/Service/ParticipantResolver.php lib/Controller/AgendaController.php lib/Controller/LiveMeetingController.php lib/Controller/MinutesController.php lib/Service/VotingService.php lib/Mcp/DecideskToolProvider.php no errors

…ent @self.relations.meeting participant filters (C3/H1/H2)

The participant schema has no meeting relation; five sites were filtering
by '@self.relations.meeting' which silently returned empty results, making
all chair/secretary and participant membership checks fail-open. Introduces
ParticipantResolver service with canonical meeting→governanceBody→participant
path (mirrors VotingService.checkQuorum) and routes AgendaController,
LiveMeetingController, MinutesController, VotingService (castVote preset
and saveShowOfHandsTally), and DecideskToolProvider.requireParticipantOrAdmin
through it.
@rubenvdlinde rubenvdlinde merged commit 8d11da2 into development May 28, 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