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
@@ -5,6 +5,7 @@ import * as crypto from 'crypto';
import { ChildProcess, spawn } from 'child_process';
import { ClustersService } from '../clusters/clusters.service';
import { HelmService, LOGGING_HELM_NAMESPACE, LOGGING_HELM_RELEASE } from './helm.service';
import { userNamespace } from './k8s-workload.util';
interface ElasticsearchCredentials {
username: string;
@@ -97,9 +98,9 @@ export class ElasticsearchService implements OnModuleInit, OnModuleDestroy {
private configService: ConfigService,
private helmService: HelmService,
) {
this.ELASTIC_PASSWORD = this.configService.get('elasticsearch.password') || 'CloudHost2024!Secure';
this.FLUENTBIT_PASSWORD = this.configService.get('elasticsearch.fluentbitPassword') || 'FluentBit2024!Writer';
this.KIBANA_SYSTEM_PASSWORD = this.configService.get('elasticsearch.kibanaPassword') || 'Kibana2024!System';
this.ELASTIC_PASSWORD = this.configService.get('elasticsearch.password') || '';
this.FLUENTBIT_PASSWORD = this.configService.get('elasticsearch.fluentbitPassword') || '';
this.KIBANA_SYSTEM_PASSWORD = this.configService.get('elasticsearch.kibanaPassword') || '';
}
async onModuleInit(): Promise<void> {
@@ -649,7 +650,7 @@ export class ElasticsearchService implements OnModuleInit, OnModuleDestroy {
generateUserCredentials(userId: string): ElasticsearchCredentials {
const hash = crypto.createHash('sha256').update(`${userId}-${this.ELASTIC_PASSWORD}`).digest('hex');
return {
username: `user-${userId.split('-')[0]}`,
username: userNamespace(userId),
password: hash.substring(0, 24),
};
}
@@ -666,16 +667,16 @@ export class ElasticsearchService implements OnModuleInit, OnModuleDestroy {
* Get index pattern for a user's applications
*/
getIndexPattern(userId: string): string {
const userPrefix = userId.split('-')[0];
return `logs-user-${userPrefix}-*`;
return `logs-${userNamespace(userId)}-*`;
}
/**
* Build must clauses for user log isolation (new + legacy fields).
*/
buildUserLogMustClauses(userId: string, filters: LogSearchFilters = {}): any[] {
const userPrefix = userId.split('-')[0];
const namespace = `user-${userPrefix}`;
// Full-UUID namespace — a truncated prefix would match other tenants'
// namespaces and leak their logs.
const namespace = userNamespace(userId);
const must: any[] = [
{
@@ -758,7 +759,7 @@ export class ElasticsearchService implements OnModuleInit, OnModuleDestroy {
}
getUserIndexPattern(userId: string): string {
return `logs-user-${userId.split('-')[0]}-*`;
return `logs-${userNamespace(userId)}-*`;
}
private elasticsearchFetch(url: string, auth: string, body: unknown): Promise<Response> {