fix(platform): apply production hardening from audit plan

Close billing, tenancy, migration, build, and CI/CD gaps identified in the
audit: wallet/gateway guards, full-UUID namespaces, idempotent migrations with
base schema, stateful service stability, safer Dockerfiles/git builds, and
platform chart hardening (Redis auth, RollingUpdate, backups, Swagger off).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
keyhan
2026-07-02 19:35:07 +03:30
parent 34c110be6a
commit 22359be40e
55 changed files with 4883 additions and 381 deletions
@@ -14,7 +14,11 @@ import {
import { AuthGuard } from '@nestjs/passport';
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { BillingService } from './billing.service';
import { assertStubGatewayAllowed } from './payment-gateway.util';
import {
assertStubGatewayAllowed,
issueGatewayTrackingCode,
assertGatewayTrackingCodeValid,
} from './payment-gateway.util';
import { AppLifecycleService } from '../lifecycle/app-lifecycle.service';
import { ApplicationsService } from '../applications/applications.service';
import { ChargeWalletDto, PayApplicationDto } from './dto/billing.dto';
@@ -43,8 +47,11 @@ export class BillingWalletController {
}
@Post('wallet/charge')
@ApiOperation({ summary: 'Charge my wallet (self top-up)' })
@ApiOperation({ summary: 'Charge my wallet (self top-up — stub gateway, dev/staging only)' })
async chargeMyWallet(@Request() req: any, @Body() dto: ChargeWalletDto) {
// Direct self-credit is only for environments with the stub gateway enabled.
// In production a real payment gateway must credit wallets.
assertStubGatewayAllowed();
return this.billingService.chargeWallet(req.user.id, dto.amount, dto.description || 'Self top-up');
}
@@ -160,7 +167,7 @@ export class BillingWalletController {
@Body() body: { amount: number; description?: string; callbackUrl: string },
) {
assertStubGatewayAllowed();
const trackingCode = `PAY-${Date.now()}-${Math.random().toString(36).substring(2, 8).toUpperCase()}`;
const trackingCode = issueGatewayTrackingCode(req.user.id, body.amount);
return {
success: true,
trackingCode,
@@ -176,6 +183,8 @@ export class BillingWalletController {
@Body() body: { trackingCode: string; amount: number },
) {
assertStubGatewayAllowed();
// The tracking code binds user + amount at initiate time; reject tampered amounts.
assertGatewayTrackingCodeValid(body.trackingCode, req.user.id, body.amount);
await this.billingService.chargeWallet(
req.user.id,
body.amount,