Found while fixing review finding F4 on PR #153, which introduced a new
portal.judging.results.export feature so that the results-export endpoint is genuinely restricted
(previously it checked a feature the participant role already had, so any competitor could export
the full ranking CSV once the stage reached finished).
What happens
src/modules/judging/frontend/[orgSlug]/portal/results/page.tsx:155 renders the CSV Export
button unconditionally. With PR #153's fix in place, a participant who clicks it now gets a raw JSON
403 in a new tab.
That is the correct server behaviour — and a bad experience. The button should not be offered to
someone who cannot use it.
Expected
Hide or disable the Export button behind portal.judging.results.export, the same feature the
endpoint checks. The portal already has the caller's resolved features available client-side (see how
sibling portal screens gate actions, e.g. the peer-voting button in PR #155 which disables itself with
a visible reason). Disabled-with-a-reason is friendlier than hidden if organisers want participants to
know an export exists.
Keep the page itself on portal.judging.results.view — viewing the published ranking is not the same
permission as exporting the whole CSV.
Deploy note carried by PR #153
Existing tenants need yarn mercato auth sync-role-acls before judges can export, since
portal.judging.results.export is a newly declared feature. Flagged here so it is not lost: it is
stated in PR #153's comment but has not been run.
Found while fixing review finding F4 on PR #153, which introduced a new
portal.judging.results.exportfeature so that the results-export endpoint is genuinely restricted(previously it checked a feature the
participantrole already had, so any competitor could exportthe full ranking CSV once the stage reached
finished).What happens
src/modules/judging/frontend/[orgSlug]/portal/results/page.tsx:155renders the CSV Exportbutton unconditionally. With PR #153's fix in place, a participant who clicks it now gets a raw JSON
403in a new tab.That is the correct server behaviour — and a bad experience. The button should not be offered to
someone who cannot use it.
Expected
Hide or disable the Export button behind
portal.judging.results.export, the same feature theendpoint checks. The portal already has the caller's resolved features available client-side (see how
sibling portal screens gate actions, e.g. the peer-voting button in PR #155 which disables itself with
a visible reason). Disabled-with-a-reason is friendlier than hidden if organisers want participants to
know an export exists.
Keep the page itself on
portal.judging.results.view— viewing the published ranking is not the samepermission as exporting the whole CSV.
Deploy note carried by PR #153
Existing tenants need
yarn mercato auth sync-role-aclsbefore judges can export, sinceportal.judging.results.exportis a newly declared feature. Flagged here so it is not lost: it isstated in PR #153's comment but has not been run.