From c11dc27c27de17b0eacc55143236848987109636 Mon Sep 17 00:00:00 2001 From: smartdev Date: Sat, 17 Oct 2026 23:59:20 +0100 Subject: [PATCH] Fix #694,695,696,697 --- src/auth/jwt.service.ts | 13 ++++++++++--- src/health/health.controller.ts | 3 +++ src/prisma/prisma.service.ts | 10 ++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/auth/jwt.service.ts b/src/auth/jwt.service.ts index 8f79f19..92ae8f4 100644 --- a/src/auth/jwt.service.ts +++ b/src/auth/jwt.service.ts @@ -8,6 +8,7 @@ import { validateJwtSecret } from "./jwt-secret.validator"; export interface JwtPayload { walletAddress: string; + type?: "access" | "refresh"; role?: string; admin?: boolean; iss?: string; @@ -52,7 +53,7 @@ export class JwtService { * Token expires in 1 hour. */ sign(walletAddress: string): string { - const payload: JwtPayload = { walletAddress, jti: crypto.randomUUID() }; + const payload: JwtPayload = { walletAddress, type: "access", jti: crypto.randomUUID() }; const options: jwt.SignOptions = { algorithm: 'HS256', expiresIn: '1h', @@ -71,7 +72,7 @@ export class JwtService { * Token expires in 1 hour. */ signWithRole(walletAddress: string, role: string, admin = false): string { - const payload: JwtPayload = { walletAddress, role, admin, jti: crypto.randomUUID() }; + const payload: JwtPayload = { walletAddress, type: "access", role, admin, jti: crypto.randomUUID() }; const options: jwt.SignOptions = { algorithm: 'HS256', expiresIn: '1h', @@ -97,9 +98,15 @@ export class JwtService { algorithms: ['HS256'], issuer: this.issuer, audience: this.audience, - }) as JwtPayload & { jti?: string }; + }) as JwtPayload & { jti?: string; type?: string }; + + if (decoded.type === "refresh") { + throw new UnauthorizedException("Cannot use refresh token as access token"); + } + return { walletAddress: decoded.walletAddress, + type: decoded.type, role: decoded.role, admin: decoded.admin, }; diff --git a/src/health/health.controller.ts b/src/health/health.controller.ts index 6b17276..3c80e32 100644 --- a/src/health/health.controller.ts +++ b/src/health/health.controller.ts @@ -488,6 +488,9 @@ export class HealthController { } else { // #421 — Report waiting job counts for known Bull queues so ops can // detect build-up before processing latency becomes user-visible. + // #695 — verify active Redis connectivity via PING before querying queue keys + await this.withTimeout(this.redis.ping(), 'Redis PING'); + const queueNames = (this.config.get('HEALTH_QUEUE_NAMES') ?? 'claims,oracle') .split(',') .map(n => n.trim()) diff --git a/src/prisma/prisma.service.ts b/src/prisma/prisma.service.ts index 3ecfcf2..b02c5e0 100644 --- a/src/prisma/prisma.service.ts +++ b/src/prisma/prisma.service.ts @@ -81,6 +81,16 @@ export class PrismaService extends PrismaClient implements OnModuleInit, OnModul } async onModuleInit() { + // #696 — Handle SIGTERM / SIGINT signals gracefully + process.once('SIGTERM', async () => { + this.logger.log('SIGTERM signal received: disconnecting Prisma client...'); + await this.onModuleDestroy(); + }); + process.once('SIGINT', async () => { + this.logger.log('SIGINT signal received: disconnecting Prisma client...'); + await this.onModuleDestroy(); + }); + const maxRetries = 5; let delayMs = 1000; for (let attempt = 1; attempt <= maxRetries; attempt++) {