Skip to content

fix(api-keys): implement write-time cycle detection for replacedById …#379

Open
yunus-dev-codecrafter wants to merge 1 commit into
ChainForgee:mainfrom
fikrah-Tech:bugfix/api-key-rotation-cycle-guard
Open

fix(api-keys): implement write-time cycle detection for replacedById …#379
yunus-dev-codecrafter wants to merge 1 commit into
ChainForgee:mainfrom
fikrah-Tech:bugfix/api-key-rotation-cycle-guard

Conversation

@yunus-dev-codecrafter

Copy link
Copy Markdown
Contributor

closes #260

Summary

Add assertNoCycle guard to prevent circular ApiKey.replacedBy self-relation chains at write time. The rotate method in ApiKeysService previously had no cycle detection — if any code path set replacedById to an existing ancestor key (e.g., A→B→A), the chain-walking code would loop infinitely.

Closes #260

Testing

TypeScript compilation passes with no errors:

cd app/backend
npx tsc --noEmit
# No errors related to cycle-check or api-keys

Unit tests added in api-keys.service.spec.ts for the assertNoCycle function:

Test Scenario
rejects a 2-node cycle A.replacedById = B; calling assertNoCycle('B', 'A') → throws BadRequestException
passes when no cycle exists B.replacedById = null; calling assertNoCycle('A', 'B') → resolves
rejects a chain that already contains a cycle X→Y→Z→X (pre-existing); calling assertNoCycle('newKey', 'X') → throws BadRequestException
throws NotFound if a key in the chain is missing Calling with a non-existent id → throws NotFoundException

To run the tests:

cd app/backend
npm test -- --testPathPatterns='api-keys.service.spec'

(Note: Requires jest v29+ and ts-jest v29+ to be properly installed.)

Screenshots

N/A

Checklist

  • Tests added or updated for new/changed behavior
  • Existing tests pass (requires jest infrastructure setup)
  • No secrets, keys, or seed phrases committed
  • Follows the coding conventions in the relevant service README
  • PR is focused on a single concern

Files changed

  • src/api-keys/cycle-check.ts (new) — assertNoCycle guard: walks the replacedBy chain from the candidate replacement, tracking visited IDs in a Set. Throws BadRequestException (CyclicRotation) if the original key or a duplicate is encountered.
  • src/api-keys/api-keys.service.ts — imports and calls assertNoCycle(existing.id, replacement.id, tx) in the rotate method after creating the replacement key but before updating the old key.
  • src/api-keys/api-keys.service.spec.ts — 4 new test cases covering cycle rejection, happy path, pre-existing cycle, and missing key.

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.

ApiKey cycles detection on replacedById

1 participant