Skip to content

Gate matrix subject actions at the subject's site scope#97

Open
tgerke wants to merge 1 commit into
mainfrom
fix/matrix-site-permissions
Open

Gate matrix subject actions at the subject's site scope#97
tgerke wants to merge 1 commit into
mainfrom
fix/matrix-site-permissions

Conversation

@tgerke

@tgerke tgerke commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Found during the docs screenshot work on #96: the subject matrix gated its per-subject actions (lifecycle transitions and break-the-blind) on usePermissions(studyId) with no site, and effectivePermissions deliberately counts only study-wide grants at study scope. Site-scoped coordinators and investigators — the seeded demo personas, and the usual shape of site staff grants — therefore never saw the menus the permission model intends them to use, while the server would have authorized the same actions.

Change

  • MatrixPage: each SubjectLifecycle row now resolves permissions at the subject's site (usePermissions(studyId, subject.siteId)), the same pattern FormEntryPage already uses for signing. React Query caches by (studyId, siteId), so it costs one fetch per site, not per row.
  • queries.test.ts: new test pinning the scoping contract the UI depends on — a site-scoped data_entry grant returns [] at study scope and subject.enroll/data.enter when the query names the site. The fixture's makeUser gains an optional siteId, since every existing fixture granted study-wide, which is why this never surfaced.

Study-level gating elsewhere on the page (export.data for casebook links) is unchanged and correct; a survey of the other usePermissions(studyId) callers (builder, coding, team, workbench, study page) shows they gate genuinely study-scoped features.

Verification

  • Full api test suite passes (255 tests, including the new one).
  • pnpm --filter @edc-core/web typecheck clean.
  • Driven in the browser against the dev stack: demo-coord (site-scoped) now sees status menus on their site's subjects in both the demo and repeating-groups studies, including Enroll/Screen fail for the screening subject; demo-cra (monitor, no subject.enroll/data.unblind) sees the full matrix with no menus.

Site-scoped grants confer nothing at study scope, so gating the
lifecycle and break-the-blind menus on study-level permissions hid them
from the coordinators and investigators who perform them. Resolve
permissions per subject row at the subject's site, matching the
FormEntryPage pattern, and pin the endpoint's scoping contract with a
test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant