Study read, risk-of-bias and PDF-correction authorization¶
Seven actions on StudyController (/api/projects/{projectId}/studies) had no resource policy.
The global authenticated-user filter was their only gate, so any signed-in user could, for any
project:
- read a study by ID (
GET {studyId}), or every study's risk-of-bias fields (GET getRobStudies); - write risk-of-bias fields into any study (
POST addRob,POST addRobs), including studies of a different project from the one in the route; - submit a PDF correction with a body-supplied project, study, search and submitter, and approve or
reject any correction (
POST {studyId}/Pdf/Correction,PUT …/{correctionId}/Approve|Reject).
The study and correction IDs were never compared with the route project. These were #3335's "entry points lacking a resource policy", confirmed open on main during application-authority milestone M3b.
The rule now¶
| Action | Policy (deployed default grantees) |
|---|---|
GET {studyId}, GET getRobStudies |
ProjectViewStudiesPolicy (every active member, project Administrator group) |
POST addRob, POST addRobs |
ProjectBulkUpdateStudiesPolicy (project Administrator group) |
POST {studyId}/Pdf/Correction |
ProjectSubmitPdfCorrectionsPolicy (every active member, project Administrator group) |
PUT …/Approve, PUT …/Reject |
ProjectApprovePdfCorrectionsPolicy (project Administrator group) |
- The two correction policies are new constants for activities (
SubmitPdfCorrections,ApprovePdfCorrections) whoseResourceSecurity.jsondefaults already existed but which no endpoint used. The registration loop inProgram.csregisters them; no host change is needed. - Risk-of-bias writes use the bulk study-update grant: they change stored study data in bulk. Starting a batch Risk of
Bias job is a separate activity,
CalculateRob(Calculate Risk of Bias authorization); both default to the project Administrator group. - Every study or correction an action touches must belong to the route project (and, for a correction,
to the route study). Otherwise the answer is
404and nothing is written. A batch naming one foreign or unknown study writes nothing: all studies are checked before any is changed. - A submitted correction takes its project and study from the route, its search from the study, and its
submitter from the signed-in user. The body's
ProjectId,StudyId,SearchIdandInvestigatorIdare ignored. - Approve and Reject now return the study they resolved (they previously mapped an un-awaited task).
The web app calls none of these actions. Callers that relied on sign-in alone now receive 403
(not permitted on the route project) or 404 (ID not in the route project).
Validation and rollout¶
StudyEndpointAuthorizationTests drives real HTTP requests through the global authentication filter,
the policies built by the same loop as Program.cs, the production authorization handler and the
deployed ResourceSecurity.json. For every action it covers owner, project administrator, ordinary
member and non-member; anonymous 401 with no read; refusal with no study or correction read and no
write; foreign-study and foreign-correction 404 with no write; an all-or-nothing batch; and server-side
attribution of a submitted correction. 28 of its 46 cases fail against the previous controller.
This security correction is unflagged: a runtime switch must not reopen the hole. It needs no data migration. In enforced application-authority mode these project policies are decided like every other project policy. Deploy with the normal API release.