Skip to content

Comments

Add prerequisite challenge features#41

Open
yulmwu wants to merge 4 commits intomainfrom
feat/prerequisite-challs
Open

Add prerequisite challenge features#41
yulmwu wants to merge 4 commits intomainfrom
feat/prerequisite-challs

Conversation

@yulmwu
Copy link
Member

@yulmwu yulmwu commented Feb 24, 2026

A new feature has been introduced that requires solving a prerequisite challenge before accessing a subsequent one. Until the prerequisite (previous) challenge is solved, the next challenge remains in a Locked state. This restriction is enforced at the team level, just like flag submissions.

Locked challenges are subject to the following restrictions:

  • The description cannot be viewed.
  • Challenge files cannot be downloaded.
  • A stack cannot be created.
  • Flag submission is not allowed.

The following fields have been added to the REST API challenge response. The previous_challenge family is optional:

  • is_locked : boolean
  • previous_challenge_id : optional int
  • previous_challenge_title : optional string
  • previous_challenge_category : optional string

Additionally, a new HTTP status code 403 challenge locked has been introduced in some API responses, with the error identifier ErrChallengeLocked.

This change also includes support for updating previous_challenge_id via the challenge update API. The business validation logic for checking whether the prerequisite challenge has been solved is as follows:

func (s *CTFService) ensureUnlocked(ctx context.Context, userID int64, challenge *models.Challenge) error {
	if challenge.PreviousChallengeID == nil || *challenge.PreviousChallengeID <= 0 {
		return nil
	}

	if userID <= 0 || s.submissionRepo == nil {
		return ErrChallengeLocked
	}

	solved, err := s.submissionRepo.HasCorrect(ctx, userID, *challenge.PreviousChallengeID)
	if err != nil {
		return fmt.Errorf("ctf.ensureUnlocked: %w", err)
	}

	if !solved {
		return ErrChallengeLocked
	}

	return nil
}

For more details, please refer to the source code.


image

@yulmwu yulmwu added this to the New features milestone Feb 24, 2026
@yulmwu yulmwu added enhancement New feature or request feature labels Feb 24, 2026
@yulmwu yulmwu requested a review from Copilot February 24, 2026 02:39
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request introduces a prerequisite challenge feature that allows challenges to be locked until a previous challenge is solved. The feature is enforced at the team level and includes comprehensive validation, testing, and documentation updates.

Changes:

  • Added previous_challenge_id field to the Challenge model with database support
  • Implemented ensureUnlocked validation in CTFService and StackService to check prerequisite completion
  • Added TeamSolvedChallengeIDs repository method and isChallengeLocked handler logic
  • Updated REST API to include locked challenge responses with limited information
  • Added comprehensive test coverage for the locked challenge workflow

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
internal/models/challenge.go Added PreviousChallengeID field to Challenge model
internal/service/ctf_service.go Added ensureUnlocked validation and updated Create/Update/SubmitFlag/RequestChallengeFileDownload methods
internal/service/stack_service.go Added ensureUnlocked validation to GetOrCreateStack method
internal/service/errors.go Added ErrChallengeLocked error constant
internal/repo/submission_repo.go Added TeamSolvedChallengeIDs method for checking solved challenges
internal/http/handlers/handler.go Added optionalUserID helper and locked challenge response logic to ListChallenges
internal/http/handlers/types.go Added optionalInt64 type and locked challenge response structures
internal/http/handlers/errors.go Added error mapping for ErrChallengeLocked to HTTP 403
internal/service/ctf_service_test.go Added comprehensive tests for prerequisite validation and locked challenge workflows
internal/service/stack_service_test.go Added test for locked stack creation
internal/http/integration/challenges_test.go Added integration test for locked challenge flow
internal/http/integration/stacks_test.go Added integration test for locked stack creation
internal/http/handlers/handler_test.go Added handler-level tests for locked challenges
scripts/generate_dummy_sql/sql_writer.py Updated SQL generation to include previous_challenge_id field
scripts/generate_dummy_sql/generator.py Updated challenge tuple to include previous_challenge_id
scripts/generate_dummy_sql/defaults/data.yaml Added example challenges with prerequisites
docs/docs/challenges.md Updated API documentation for locked challenges
docs/docs/admin.md Updated admin API documentation for prerequisite field
docs/docs/stacks.md Added 403 error documentation for locked challenges
docs/docs/report.schema.json Added previous_challenge_id to report schema

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@yulmwu
Copy link
Member Author

yulmwu commented Feb 24, 2026

There are no issues with CI, but CodeCov is not functioning properly. It may be a temporary server error, so I will wait a bit longer.

image

@codecov
Copy link

codecov bot commented Feb 24, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant