Skip to content

fix(permissions): require score set visibility to read a score calibration - #895

Merged
bencap merged 1 commit into
release-2026.2.7.4from
bugfix/bencap/sa-8/scores-exposed-via-public-calibrations
Sep 28, 2026
Merged

bencap merged 1 commit into
release-2026.2.7.4from
bugfix/bencap/sa-8/scores-exposed-via-public-calibrations

Conversation

@bencap

@bencap bencap commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

A score calibration is now readable only by users who can read its score set. Before this change, a published calibration on a private score set exposed that score set's variants through the calibration's variant routes.

  • Publishing: a calibration can't be published while its score set is private. The publish route returns 400; this check was previously commented out.
  • Reading: calibration READ now also requires READ on the score set. Denials are 404, matching the variant routes. This protects calibrations that were already published this way, and ones written by paths that skip the publish route.
  • /score-calibrations/me: returns only calibrations the user can still read.

Existing rows are unchanged. Clearing private/primary on public calibrations of private score sets is a separate data fix to run at deploy.

Tests

Adds permission, lib, and router tests. Most of the test changes update fixtures that relied on the old behavior, such as calibrations published on unpublished score sets.

…ation

A calibration could be published while its score set was still private, and the calibration READ rule
permitted any non-private calibration without consulting the score set. The variant routes under
/score-calibrations/{urn} check calibration READ only, so an unauthenticated caller holding the URN of
such a calibration received the private score set's variants, including every score and count column.
Any contributor could create and publish one, releasing data before the score set's owner did.

Close both halves. Publishing a calibration now fails with 400 while its score set is private, the
check that had been left commented out since calibrations were introduced. Calibration READ now also
requires READ on the score set, delegated to the score set's own rule, so calibrations already
published this way stop leaking on deploy, and writers that bypass the publish route (an admin move,
the calibration loader scripts) cannot reopen it. Denials are 404, matching the variant routes. This
also withholds a private calibration from its creator once they can no longer read the score set.

/score-calibrations/me returned every calibration a user had created with no permission check, so a
contributor removed from a private score set still received its calibrations' ranges and tmp URN. It
now filters on READ.

Existing rows are left as they are; clearing private and primary on public calibrations of private
score sets is a separate data fix.

Most of the test churn is fixtures that modelled the leaked state: calibrations published on
unpublished score sets, mock score sets with no private attribute, and dump score sets carrying a
published date with private left true.
@bencap
bencap merged commit a95e981 into release-2026.2.7.4 Sep 28, 2026
4 of 5 checks passed
@bencap bencap mentioned this pull request Sep 28, 2026
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