The member-facing projects surface — My Projects on the user
dashboard (/dashboard/projects), the non-admin doorway into the hub.
Registered via user_dashboard_tabs/0 with a live_view, so core's
authenticated route table generates the route (no admin permission
involved — the page runs in the :phoenix_kit_authenticated
live_session like My Orders / My Tickets).
The membership gate (load-bearing)
Embedded hub LVs trust their host (session["current_user_uuid"], no
internal authz on mount) — so THIS page is the authorization boundary:
it only lists projects from the viewer's OWN membership rows
(Members.accessible_projects/1 — memberships AND anything the
viewer's teams, departments, or site roles grant), and ?open=
resolves against that
same list — a foreign uuid simply doesn't open. Inside an opened
project the normal Authz.can?/4 membership floors apply to every
event (owner > manager > member > viewer).
Opening a project
?open=<uuid> (patch, deep-linkable) swaps the list for the full
project page: PopupHostLive with ProjectShowLive as the root view,
so everything the project page opens (task forms, gantt, calendar)
stacks in modals via the emit contract — no admin routes touched.