feat: support hint prerequisite chains in the Challenge CRD - #2
Merged
Conversation
Hints were reconciled as an unordered multiset, so neither their order nor any unlock dependency between them could be expressed. CTFd models hint ordering through per-hint prerequisites (the IDs of hints that must be unlocked first), which this exposes declaratively. ChallengeHint gains `prerequisites` (0-based indexes into the same hints list, since CTFd assigns hint IDs only at creation) and `anonymize`. The controller now preserves each hint's identity across reconciles: hints are created/reused, their prerequisites wired up in a second pass once every ID is known, then unwanted hints deleted. A hint whose only change is its prerequisites is patched in place rather than recreated, preserving its ID and players' unlock state. Indexes are validated for range, self-reference, and cycles.
The e2e only checked hint counts, so the new prerequisite wiring went uncovered. ctfdctl -mode verify now fetches the example challenge's hints individually (the listing omits requirements) and asserts the 25-point hint requires the 10-point one, which itself has no prerequisite.
Owner
Author
✅ e2e passed locallyRan the full suite ( ```
Also green: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Hints in the
ChallengeCRD were reconciled as an unordered multiset, so neither their order nor any unlock dependency between them could be expressed. CTFd models hint ordering through per-hint prerequisites (the IDs of hints that must be unlocked first); this PR exposes that declaratively.Changes
ChallengeHint): two new optional fieldsprerequisites []int— 0-based indexes into the samehintslist of the hints that must be unlocked first (CTFd assigns hint IDs only at creation, so prerequisites are referenced positionally).anonymize(true/false/preview) — behavior while prerequisites are unmet; no effect without prerequisites.flagshints.go): hints now keep their identity across reconciles.planHintsmatches desired↔existing by value while mapping each desired index to its real CTFd hint ID.syncHints: create/reuse → wire prerequisites in a second pass (once every ID is known, so it handles references to hints created in the same pass) → delete extras.hintsUpToDatenow also compares the resolved prerequisite chain and anonymize.challengeHintsalways fetches the full hint (the CTFd list omitsrequirements).validateHintPrereqsrejects out-of-range indexes, self-references, and cycles (DFS) — a cycle would make hints impossible to unlock.Example
Notes
Testing
go test ./...— greengolangci-lint run— 0 issuesTestHintsUpToDatePrerequisitesandTestValidateHintPrereqs; CRD + deepcopy regenerated viago generate ./apis/....