Problem
ConsentService.check_access() (spp_api_v2/services/consent_service.py, ~450) evaluates consent only when
action in ("read", "search"). For update/delete it checks scope and returns True. So the write endpoints that
use it (check_individual_access / check_group_access in routers/dependencies.py, and the group router's
update/merge checks) never evaluate consent:
A client configured with is_require_consent and write scopes can modify registrants it has no consent for, while
it cannot read them.
Expected
Decide the policy (consent required to process/modify, per docs/principles/consent-data-sharing.md), then enforce it
on every write path with the same predicate reads use (filter_response statuses no_consent / scope_mismatch),
with tests for a consent-requiring client without consent on each write endpoint.
Context
Found in the adversarial review of PR #555 (#554); pre-existing, not introduced there.
Problem
ConsentService.check_access()(spp_api_v2/services/consent_service.py, ~450) evaluates consent only whenaction in ("read", "search"). Forupdate/deleteit checks scope and returns True. So the write endpoints thatuse it (
check_individual_access/check_group_accessinrouters/dependencies.py, and the group router'supdate/merge checks) never evaluate consent:
PUT/PATCH /Individual/{id},PUT/PATCH /Group/{id}$add-member,$remove-member, member update,$merge,$splitPUT /ProgramMembership/{id}has no consent check at all (only PR fix(api_v2): REST API v2 defects found by the OpenFn adaptor (#554) #555's consent-aware refusal when no singlemembership resolves)
A client configured with
is_require_consentand write scopes can modify registrants it has no consent for, whileit cannot read them.
Expected
Decide the policy (consent required to process/modify, per
docs/principles/consent-data-sharing.md), then enforce iton every write path with the same predicate reads use (
filter_responsestatusesno_consent/scope_mismatch),with tests for a consent-requiring client without consent on each write endpoint.
Context
Found in the adversarial review of PR #555 (#554); pre-existing, not introduced there.