feat: resolve issues #491 #492 #493 #494 - #583
Merged
legend-esc merged 2 commits intoJul 25, 2026
Merged
Conversation
…end-esc#494 legend-esc#492 - Per-account Redis-backed rate limiting on POST /auth/verify - Rewrite ThrottlerGuard: dual-mode IP + per-account, Redis INCR/EXPIRE with in-memory fallback; Retry-After header on 429 - Add AccountThrottle decorator and POST /auth/verify route - Update throttler.guard.spec.ts for async canActivate + account mode legend-esc#491 - JWT logout via Redis blocklist - Sign tokens with jti (UUID v4) claim in verifyAndIssueToken - Add AuthService.logout() stores jti in Redis with remaining TTL - Add AuthService.isTokenRevoked() for guard check - Rewrite JwtAuthGuard: LRU in-memory cache for hot revoked JTIs, Redis fallback; rejects tokens without jti (legacy tokens) - Update StellarAuthStrategy to forward jti to req.user - Add POST /auth/logout route (JWT-protected, returns 200) legend-esc#493 - CertificateService error recovery + wire IPFS - Wrap Worker construction in try/catch for DataCloneError - Handle worker message with { error } field from pdf.worker.js - pdf.worker.js: wrap generation in try/catch, post errors via parentPort.postMessage({ error }) instead of throwing - Wire CertificateService.generateAndPin() into retire() - Pinata circuit breaker: IPFS failure returns null hash, retirement still succeeds with a logged warning - Add Pinata failure path tests to certificate.service.spec.ts legend-esc#494 - POST /credits/bulk parallelisation + validation - Rewrite getBulkCredits with Promise.allSettled (parallel fetches) - Filter invalid hex IDs before fetching (skip, not 400) - Add BulkCreditsDto with ArrayMaxSize(100) validation - Wire ValidationPipe on POST /credits/bulk controller route Tests: - security.e2e-spec.ts: per-account rate limit scenarios - jwt-auth.e2e-spec.ts: logout flow, jti claim, legacy token rejection Chore: - Update .gitignore: test_snapshots/, __snapshots__/, *.snap, coverage/, karma output, jest cache, build artifacts
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
Resolves #491, #492, #493, #494
#491 — JWT logout via Redis blocklist
auth.service.ts:verifyAndIssueTokennow includes ajti(UUID v4) claim in all issued tokens. Addedlogout(token)to store the jti in Redis with remaining TTL, andisTokenRevoked(jti)for guard checks.jwt-auth.guard.ts: Rewritten with LRU in-memory cache (1000-entry cap, <1ms on hit) + Redis fallback blocklist check. Tokens withoutjtiare rejected as unrevocable.stellar-auth.strategy.ts: Forwardsjtithroughreq.user.auth.controller.ts: AddedPOST /auth/logout(JWT-protected, returns 200).auth.module.ts:JwtAuthGuardprovided withAuthServicedependency properly wired.#492 — Per-account rate limiting on POST /auth/verify
throttler.guard.ts: Rewritten with dual-mode. Standard@Throttle= IP-only (in-memory, backward-compatible). New@AccountThrottle= per-account + per-IP, Redis-backed (INCR/EXPIRE with in-memory fallback). ReturnsRetry-Afterheader on 429.auth.controller.ts: AddedPOST /auth/verifywith@AccountThrottle({ accountLimit: 10, ipLimit: 50, ttl: 300_000 }).throttler.guard.spec.ts: Updated for asynccanActivate+ full account-throttle test suite.#493 — CertificateService error recovery + wired IPFS
certificate.service.ts: Worker construction wrapped in try/catch forDataCloneError. Worker messages checked for{ error }object. Pinata circuit breaker — IPFS failure returns{ pdfBuffer, ipfsHash: null }instead of throwing.pdf.worker.js: Generation wrapped in try/catch; errors posted viaparentPort.postMessage({ error })instead of throwing to uncaught handler.retirement.service.ts:CertificateServiceinjected@Optional().retire()now callsgenerateAndPin()and returns realcertificateIpfsHash; Pinata failure is logged and does not abort the retirement.certificate.service.spec.ts: Added Pinata failure tests (ECONNREFUSED, 503, success, DataCloneError).#494 — POST /credits/bulk parallelisation + validation
credits.service.ts:getBulkCreditsrewritten withPromise.allSettledfor parallel fetches. Invalid hex IDs skipped (partial result, not 400). Each fetched credit individually cached.credits.controller.ts:POST /bulknow usesBulkCreditsDtowithValidationPipe.dto/bulk-credits.dto.ts: New DTO with@ArrayMaxSize(100),@ArrayMinSize(1).Tests
security.e2e-spec.ts: Per-account rate limit scenarios (issue Add rate limiting per Stellar address toPOST /auth/verify— brute-force protection for SEP-10 challenges #492)jwt-auth.e2e-spec.ts: Logout flow, jti claim, legacy token rejection (issue ImplementPOST /api/v1/auth/logout— JWT invalidation via Redis blocklist #491)Chore
.gitignore:test_snapshots/,__snapshots__/,*.snap,coverage/, karma output, jest cache excluded.