Skip to content

PM-5961: only allow deleting submissions while their submission phase is open - #7270

Merged
jmgasper merged 1 commit into
developfrom
PM-5961
Aug 25, 2026
Merged

PM-5961: only allow deleting submissions while their submission phase is open#7270
jmgasper merged 1 commit into
developfrom
PM-5961

Conversation

@jmgasper

Copy link
Copy Markdown
Collaborator

What was broken

In Design challenges the submitter could still delete a submission after the phase that created it had ended. A checkpoint submission stayed deletable for the whole Submission phase, so it could be removed after it had already passed Checkpoint Screening and been scored in Checkpoint Review — exactly the scenario in the PM-5961 recording.

Expected behaviour: a submission can only be deleted while the phase that produced it is open (Checkpoint Submission for checkpoint submissions, Submission for contest submissions), and nothing is deletable once every submission phase is closed.

Root cause

SubmissionsTable computed the delete permission from a single submissionPhaseStartDate prop, which the container derived as the start date of any open Submission or Checkpoint Submission phase:

const allowDelete = submissionPhaseStartDate
  && moment(subObject.submissionDate).isAfter(submissionPhaseStartDate);

Two problems:

  1. submissionDate is not a field on member submissions (they expose created), so moment(undefined) resolved to "now". The expression collapsed to "now is after the open phase start", i.e. always true whenever any submission phase was open.
  2. Even with the right date field, the check never looked at the submission's own type, so a checkpoint submission was treated as belonging to the open Submission phase.

What was changed

  • Added belongsToActiveSubmissionPhase() to utils/challenge-detail/submission-limit. It reuses the existing getActiveSubmissionType() phase precedence (already used for submission limits and for typing new uploads) to decide whether a submission was created by the currently open submission phase, and returns false when no submission phase is open at all. Both the V6 type and the legacy submissionType fields are supported.
  • SubmissionsTable now derives allowDelete from that helper against challenge.phases, so:
    • checkpoint submissions are deletable only during Checkpoint Submission,
    • contest submissions are deletable only during Submission,
    • nothing is deletable during screening / review / appeals / after completion.
  • Removed the now-unused submissionPhaseStartDate prop from the submission management container and components (it existed only to feed the old check).

The existing "You can delete this submission only after the review is complete" workflow-run gating and the COMPLETED / Design-track conditions on the delete button are unchanged.

Any added/updated tests

__tests__/shared/utils/challenge-detail/submission-limit.test.js — new belongsToActiveSubmissionPhase suite:

  • allows deleting a checkpoint submission (current and legacy type fields) while the Checkpoint Submission phase is open
  • blocks deleting a checkpoint submission once the Submission phase opens, while still allowing contest submissions
  • blocks deleting anything once every submission phase is closed (Checkpoint Review / Review open)
  • resolves to false for missing submissions or missing phases

Also updated the SubmissionsTable shallow snapshot, which now records the boolean allowDelete={false} prop (previously undefined, and therefore omitted, because the test fixture supplies no submissionPhaseStartDate).

Validation run: npm run lint (clean), npm run jest — 380 passed, 141 snapshots passed, 0 failures; npm run build succeeds.

The companion API enforcement is in topcoder-platform/review-api-v6 PM-5961.

🤖 Generated with Claude Code

… is open

What was broken
In Design challenges the submitter could still delete a submission after the
phase that created it had ended. In particular a checkpoint submission stayed
deletable for the whole Submission phase, so it could be removed after it had
already been screened and scored in Checkpoint Screening / Checkpoint Review.

Root cause
SubmissionsTable computed the delete permission from a single
"submissionPhaseStartDate" prop, which was the start date of *any* open
Submission or Checkpoint Submission phase, and compared it against
subObject.submissionDate - a field that member submissions do not carry (they
expose "created"). The comparison therefore resolved to "now is after the open
phase start", i.e. the delete button was enabled for every submission whenever
any submission phase was open, regardless of which phase actually produced the
submission.

What was changed
- Added belongsToActiveSubmissionPhase() to
  utils/challenge-detail/submission-limit, which reuses the existing
  getActiveSubmissionType() phase precedence to decide whether a submission was
  created by the currently open submission phase.
- SubmissionsTable now derives allowDelete from the submission's own type
  against the open phase, so checkpoint submissions stop being deletable when
  the Checkpoint Submission phase closes, and nothing is deletable once every
  submission phase is closed.
- Removed the now-unused submissionPhaseStartDate prop from the submission
  management container and components.

Any added/updated tests
- __tests__/shared/utils/challenge-detail/submission-limit.test.js: new
  belongsToActiveSubmissionPhase suite covering checkpoint deletion during the
  checkpoint phase, checkpoint deletion blocked once the Submission phase opens,
  everything blocked during screening/review, and missing submission/phase input.
- Updated the SubmissionsTable shallow snapshot for the now-boolean allowDelete
  prop.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jmgasper
jmgasper requested a review from kkartunov as a code owner August 25, 2026 04:02
@jmgasper
jmgasper merged commit 30074b3 into develop Aug 25, 2026
7 checks passed
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