Repository navigation
fix(deck): reject duplicate command-zone Oracle cards on card add - #1295
KaelSensei wants to merge 1 commit into
Conversation
POST /api/decks/[id]/cards accepted a commander or partner card that repeats the Oracle card held by the opposite command slot, bypassing the check deck create and update already enforce (#1131). A command-zone card is now compared with the opposite slot by printing ID, then by Oracle identity, and rejected with 400 before any row is written. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codex Review Summary: ❌ FailedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|



Roadmap item
I-03 Trustworthy Deck Feedback (Now) → Validate commander and partner mechanics at the deck API boundary, including imported pairs and the same Oracle card across different printings.
#1131 added the same-Oracle check to deck create (
POST /api/decks) and update (PATCH /api/decks/[id]). The command-zone card row itself is written via a third boundary,POST /api/decks/[id]/cards, which acceptedisCommander: true/isPartner: truewith no pairing check. That meant a direct request could write a partner row that reprints the commander's Oracle card, or a commander row that reprints the saved partner's.Change
src/lib/deck/commander-pairing.ts: newduplicatesOtherCommandSlot(cardId, otherSlotId). It returns false when the other slot is empty, true for the same printing without calling Scryfall, and otherwise falls back tosharesOracleIdentity.src/app/api/decks/[id]/cards/route.ts: for a command-zone card, the route compares the partner with the deck'scommanderIdand the commander with itspartnerId. A duplicate gets a 400 with the existing message, "Commander and partner must be different cards", before any row is written. Main, sideboard and maybeboard additions skip the extra lookup and the Scryfall call.No migration, no new service and no client change. The editor's
setCommander/setPartnerflow already updates the deck before it adds the card, and that update is validated, so legitimate flows are unaffected.This is one slice of the roadmap item, not all of it. Imported pairs reach the deck through the same validated PATCH and card-add path. This PR does not touch the roadmap item's checkbox, which is left to the chore/docs PR.
TDD
Red: I added
src/app/api/decks/[id]/cards/route.test.ts(5 sociable route tests: Prisma, auth and Scryfall mocked) and rannpx vitest run cards/route.testbefore changing the route:Green: 10/10 pass after the change.
Verification
npx tsc --noEmit: 0 errorspnpm lint: no ESLint warnings or errorspnpm test: 345 files, 3515 tests passedpnpm sonar: not run, because there is no.env.sonarin this worktree. Sonar was left to CI.🤖 Generated with Claude Code