Skip to content

fix(meetings): add an auth guard to the past-meeting admin route #3265

Open

Description

@nunoeufrasio

Requirements: FR-054 in specs/011-meeting-details-redesign/requirements.md. State model: state-matrix.md in the same directory.
Branch: PRs for this issue target the integration branch feat/meeting-details-v2, not main. Nothing in this epic reaches production until the release PR #3249 merges.
Security change (R06): ships in its own PR, into the integration branch feat/meeting-details-v2. Decided 2026-10-05 by the project owner: it does not go to main first. It ships with the rest of V2 through #3249.

Design: https://claude.ai/design/p/c70cdcac-911f-4337-9d87-3daed9d85f58?file=Meeting+Details.dc.html&via=share

Prototype settings panel: time / viewer / privacy / rsvpTracking / pastAccess / myRsvp / recur / via / pageStatus. Its look and feel differs from the current app on purpose — follow it.

Epic: #1765 · Meetings v2 epic: #1451 · Plan ID: N-03 · Size: S · Depends on: E0-03

Delivery: this ships as part of meeting details V2, side by side with the existing page, behind MEETING_V2_ENABLED_FLAG. Do not modify, refactor or delete the existing meeting details page. V1 stays fully functional and is what untargeted users see. Parent: Meetings v2 epic #1451. Full rules in #1765.
Components: follow the prototype for design, but build it from the existing lfx-* components in app/shared/components/. Extend a wrapper before forking it; create a new component only when the design can't be expressed otherwise, and say so in the PR.


Problem. /meetings/:id/details has no canActivate. It was tolerable while the route was an unreachable read-only orphan. It is not tolerable now: it hosts organizer-only write actions (attendance reconciliation, participant create / update / delete), and per GH #2251 it is becoming the surface Manage-role users are deliberately routed to. Protection today is only the Express catch-all, which authenticates but does not authorize.

Scope. Add an explicit guard aligned to the Manage-vs-View role model that #2251 establishes. Decide and implement what a View-role or anonymous user hitting the URL directly sees — redirect to the public page is the likely answer, not a 404.

Acceptance criteria

Added 2026-10-05: E0-03 decision (meeting-surface-boundary.md, merged in #3268), § Who sees what on /details:

  • The guard resolves organizer through the detail path (GET /api/past-meetings/:uid, isPastMeetingOrganizer), not the list's.
  • Organizer → the admin page. Signed-in non-organizer → redirect to /meetings/:id. Anonymous → the existing login redirect.
  • 400/403/404 → /meetings/not-found. Any other failure → a load-error state with retry; the admin page stays closed.
  • Manage role = organizers only, pending @MRashad26's confirmation on docs(meetings): record the public and admin meeting surface boundary #3268.

Filed from meeting-details-redesign-implementation-plan.md (revised 2026-09-23).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmeetingsAn epic, feature, story, task, or bug related to meetings.

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions