Harden platform security, reliability, and CI after full audit.
Close deployment IDOR and gate stub payment endpoints, add production secret validation, health probes, Redis-backed build progress, GitHub Actions CI, expanded tests, billing/k8s refactors, and ops runbooks. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import { Injectable, OnModuleDestroy } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import Redis from 'ioredis';
|
||||
import type { BuildProgress } from './build.service';
|
||||
|
||||
const KEY_PREFIX = 'build:progress:';
|
||||
const TTL_SECONDS = 3600;
|
||||
|
||||
@Injectable()
|
||||
export class BuildProgressStore implements OnModuleDestroy {
|
||||
private readonly redis: Redis;
|
||||
|
||||
constructor(private readonly configService: ConfigService) {
|
||||
this.redis = new Redis({
|
||||
host: this.configService.get<string>('redis.host'),
|
||||
port: this.configService.get<number>('redis.port'),
|
||||
lazyConnect: true,
|
||||
maxRetriesPerRequest: 1,
|
||||
});
|
||||
this.redis.connect().catch(() => {
|
||||
// Redis may be unavailable in local unit tests — in-memory fallback remains in BuildService.
|
||||
});
|
||||
}
|
||||
|
||||
async get(deploymentId: string): Promise<BuildProgress | null> {
|
||||
try {
|
||||
const raw = await this.redis.get(`${KEY_PREFIX}${deploymentId}`);
|
||||
return raw ? (JSON.parse(raw) as BuildProgress) : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async set(deploymentId: string, progress: BuildProgress): Promise<void> {
|
||||
try {
|
||||
await this.redis.set(
|
||||
`${KEY_PREFIX}${deploymentId}`,
|
||||
JSON.stringify(progress),
|
||||
'EX',
|
||||
TTL_SECONDS,
|
||||
);
|
||||
} catch {
|
||||
// Best-effort — local map still holds progress for this replica.
|
||||
}
|
||||
}
|
||||
|
||||
async clear(deploymentId: string): Promise<void> {
|
||||
try {
|
||||
await this.redis.del(`${KEY_PREFIX}${deploymentId}`);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
onModuleDestroy(): void {
|
||||
this.redis.disconnect();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user