Skip to content

Comments

feat: enterprise AI agent management platform (Gateway-Dashboard)#3

Merged
smouj merged 1 commit intomainfrom
claude/enterprise-ai-gateway-platform-nYr63
Feb 20, 2026
Merged

feat: enterprise AI agent management platform (Gateway-Dashboard)#3
smouj merged 1 commit intomainfrom
claude/enterprise-ai-gateway-platform-nYr63

Conversation

@smouj
Copy link
Owner

@smouj smouj commented Feb 20, 2026

Complete transformation into a production-ready enterprise platform:

API Gateway (Fastify 4 + TypeScript)

  • OpenClaw universal AI agent orchestrator with smooth weighted round-robin load balancing
  • Domain-Driven Design: domain → application → infrastructure → interface layers
  • Enterprise auth: TOTP 2FA (otplib), httpOnly JWT cookies, scrypt password hashing
  • Immutable audit log with SHA-256 cryptographic fingerprint chaining
  • Adaptive rate limiting with exponential backoff (SQLite-backed sliding windows)
  • AES-256-GCM encryption for Kilo Code API keys at rest
  • Docker container management via Docker CLI wrapper
  • WebSocket terminal with security allowlist
  • Kilo Code bridge API (proxy with encrypted credentials)
  • SQLite WAL-mode persistence with schema migrations

Next.js 15 Admin Dashboard (App Router)

  • Login with TOTP step-up flow
  • Agent CRUD with OpenClaw dispatch testing
  • Real-time audit log with chain integrity indicator
  • Docker container/image management
  • WebSocket terminal UI
  • Kilo Code configuration and TOTP/password settings

Testing (Vitest)

  • 85 gateway tests passing (10 files: unit + integration)
  • 26 dashboard tests passing (2 files: lib/utils + lib/api)
  • Coverage: gateway 83.6% lines/83.6% stmts/82.2% fns/86.6% branches (all ≥80%)
  • Coverage: dashboard 97.3% lines/97.3% stmts/85.7% fns/80.6% branches (all ≥70%)
  • Integration tests use in-memory SQLite with pool:forks isolation

Infrastructure

  • pnpm workspaces monorepo (apps/, services/, packages/*)
  • Shared TypeScript types package (@peanut/shared-types)
  • GitHub Actions CI pipeline (type-check, test, build, docker, security-audit)
  • Docker Compose for local development

https://claude.ai/code/session_01LCd1PF4LVsQDY4uAWzsm1i

Complete transformation into a production-ready enterprise platform:

**API Gateway (Fastify 4 + TypeScript)**
- OpenClaw universal AI agent orchestrator with smooth weighted round-robin load balancing
- Domain-Driven Design: domain → application → infrastructure → interface layers
- Enterprise auth: TOTP 2FA (otplib), httpOnly JWT cookies, scrypt password hashing
- Immutable audit log with SHA-256 cryptographic fingerprint chaining
- Adaptive rate limiting with exponential backoff (SQLite-backed sliding windows)
- AES-256-GCM encryption for Kilo Code API keys at rest
- Docker container management via Docker CLI wrapper
- WebSocket terminal with security allowlist
- Kilo Code bridge API (proxy with encrypted credentials)
- SQLite WAL-mode persistence with schema migrations

**Next.js 15 Admin Dashboard (App Router)**
- Login with TOTP step-up flow
- Agent CRUD with OpenClaw dispatch testing
- Real-time audit log with chain integrity indicator
- Docker container/image management
- WebSocket terminal UI
- Kilo Code configuration and TOTP/password settings

**Testing (Vitest)**
- 85 gateway tests passing (10 files: unit + integration)
- 26 dashboard tests passing (2 files: lib/utils + lib/api)
- Coverage: gateway 83.6% lines/83.6% stmts/82.2% fns/86.6% branches (all ≥80%)
- Coverage: dashboard 97.3% lines/97.3% stmts/85.7% fns/80.6% branches (all ≥70%)
- Integration tests use in-memory SQLite with pool:forks isolation

**Infrastructure**
- pnpm workspaces monorepo (apps/*, services/*, packages/*)
- Shared TypeScript types package (@peanut/shared-types)
- GitHub Actions CI pipeline (type-check, test, build, docker, security-audit)
- Docker Compose for local development

https://claude.ai/code/session_01LCd1PF4LVsQDY4uAWzsm1i
}

const envArgs = Object.entries(dto.env ?? {})
.map(([k, v]) => `-e "${k.replace(/"/g, '')}=${v.replace(/"/g, '')}"`)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: La sanitización de variables de entorno es insuficiente. El reemplazo replace(/"/g, '') puede ser bypassed con técnicas de inyección de comandos usando backticks, $() u otras técnicas de shell.

Considera usar una librería de escape apropiada o pasar las variables de entorno de forma segura sin interpolación de strings.

.join(' ');

const volumeArgs = (dto.volumes ?? [])
.map(v => `-v "${v.replace(/"/g, '')}"`)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: La sanitización de volúmenes es insuficiente. El reemplazo replace(/"/g, '') no previene inyección de comandos usando otros caracteres shell.

Considera validar el path contra un allowlist o usar path traversal checks más robustos.

exp: Date.now() + 10 * 60 * 1000,
nonce: randomBytes(8).toString('hex'),
};
return Buffer.from(JSON.stringify(payload)).toString('base64url');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRITICAL: El token temporal no está firmado - cualquiera puede modificarlo. El uso de base64url sin firma permite que un atacante modifique el userId o extienda la expiración.

Considera usar JWT firmados o HMAC para el temp token.

'git', 'node', 'python3', 'pip',
]);

const FORBIDDEN_PATTERNS = /\b(rm|rmdir|dd|mkfs|fdisk|format|kill|killall|shutdown|reboot|halt|sudo|su|chmod|chown|passwd|crontab|systemctl|service)\b/;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: El patrón FORBIDDEN_PATTERNS usa word boundaries que pueden ser bypassed. Además, el spawn de /bin/sh sin sandboxing permite ejecución arbitraria si se bypassan los filtros.

email: user.email,
role: user.role,
totpVerified: false,
sessionId: Math.random().toString(36).slice(2),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Math.random() no es criptográficamente seguro para generar session IDs. Considera usar crypto.randomBytes() o crypto.randomUUID().

email: user.email,
role: user.role,
totpVerified: true,
sessionId: Math.random().toString(36).slice(2),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Math.random() no es criptográficamente seguro para generar session IDs. Considera usar crypto.randomBytes() o crypto.randomUUID().

await authService.createUser(
'admin@peanut.local',
'Administrator',
process.env['DEFAULT_ADMIN_PASSWORD'] ?? 'PeanutAdmin@2024!',
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: La contraseña por defecto tiene fallback hardcodeado. Si DEFAULT_ADMIN_PASSWORD no está seteado, se usa una contraseña conocida. Considera requerir explícitamente la variable de entorno.


// Clean old windows
const cutoff = new Date(now - cfg.windowMs * 10).toISOString();
db.prepare('DELETE FROM rate_limit_windows WHERE window_start < ?').run(cutoff);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: La limpieza de ventanas antiguas corre en cada request. Para alto tráfico, considera usar un job programado o TTL nativo de la base de datos.

if (!_db) {
const DATA_DIR = process.env['DATA_DIR'] ?? join(process.cwd(), 'data');
const dbPath = DATA_DIR === ':memory:' ? ':memory:' : join(DATA_DIR, 'gateway.db');
if (DATA_DIR !== ':memory:') mkdirSync(DATA_DIR, { recursive: true });
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: La base de datos SQLite usa modo WAL que puede no ser apropiado para todos los entornos de deployment. Considera documentar esta elección.

@kiloconnect
Copy link

kiloconnect bot commented Feb 20, 2026

Code Review Summary

Status: 9 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 1
WARNING 6
SUGGESTION 2
Issue Details (click to expand)

CRITICAL

File Line Issue
services/gateway/src/application/services/auth.service.ts 214 El token temporal no está firmado - permite modificación por atacantes

WARNING

File Line Issue
services/gateway/src/application/services/docker.service.ts 107 Sanitización insuficiente en variables de entorno (inyección de comandos)
services/gateway/src/application/services/docker.service.ts 115 Sanitización insuficiente en volúmenes (inyección de comandos)
services/gateway/src/interfaces/ws/terminal.handler.ts 16 Patrón FORBIDDEN_PATTERNS puede ser bypassed; shell sin sandbox
services/gateway/src/interfaces/http/routes/auth.routes.ts 45 Math.random() no es criptográficamente seguro para session IDs
services/gateway/src/interfaces/http/routes/auth.routes.ts 81 Math.random() no es criptográficamente seguro para session IDs
services/gateway/src/server.ts 100 Contraseña por defecto con fallback hardcodeado

SUGGESTION

File Line Issue
services/gateway/src/application/services/rate-limit.service.ts 35 Limpieza de ventanas antiguas en cada request puede impactar performance
services/gateway/src/infrastructure/database/db.ts 11 Modo WAL de SQLite puede no ser apropiado para todos los entornos
Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

File Line Issue
N/A - No additional issues found outside diff
Files Reviewed (40+ files)
  • .env.example - Environment configuration template
  • .github/workflows/ci.yml - CI/CD pipeline configuration
  • services/gateway/src/application/services/auth.service.ts - 1 issue
  • services/gateway/src/application/services/crypto.service.ts - No issues
  • services/gateway/src/application/services/docker.service.ts - 2 issues
  • services/gateway/src/application/services/openclaw.service.ts - No issues
  • services/gateway/src/application/services/rate-limit.service.ts - 1 issue
  • services/gateway/src/application/services/audit.service.ts - No issues
  • services/gateway/src/infrastructure/database/db.ts - 1 issue
  • services/gateway/src/infrastructure/database/user.repository.ts - No issues
  • services/gateway/src/infrastructure/database/agent.repository.ts - No issues
  • services/gateway/src/infrastructure/database/audit.repository.ts - No issues
  • services/gateway/src/infrastructure/kilo/kilo.client.ts - No issues
  • services/gateway/src/interfaces/http/routes/auth.routes.ts - 2 issues
  • services/gateway/src/interfaces/http/routes/agents.routes.ts - No issues
  • services/gateway/src/interfaces/http/routes/audit.routes.ts - No issues
  • services/gateway/src/interfaces/http/routes/docker.routes.ts - No issues
  • services/gateway/src/interfaces/http/routes/kilo.routes.ts - No issues
  • services/gateway/src/interfaces/ws/terminal.handler.ts - 1 issue
  • services/gateway/src/domain/agent/agent.entity.ts - No issues
  • services/gateway/src/domain/auth/user.entity.ts - No issues
  • services/gateway/src/domain/audit/audit.entity.ts - No issues
  • services/gateway/src/domain/errors.ts - No issues
  • services/gateway/src/server.ts - 1 issue
  • apps/dashboard/src/lib/auth.ts - No issues
  • apps/dashboard/src/lib/api.ts - No issues
  • apps/dashboard/src/app/auth/login/page.tsx - No issues
  • apps/dashboard/src/app/dashboard/settings/page.tsx - No issues
  • apps/dashboard/src/app/dashboard/docker/page.tsx - No issues
  • apps/dashboard/src/app/dashboard/terminal/page.tsx - No issues
  • Multiple test files - No issues

Fix these issues in Kilo Cloud

@smouj smouj merged commit fc72e82 into main Feb 20, 2026
14 checks passed
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e507d0827

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +22 to +24
const url = path.startsWith('/api/gateway')
? path // Next.js rewrite proxy
: `${API_BASE}/api/v1${path}`;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Badge Forward auth cookies in server-side dashboard API calls

This helper builds an absolute gateway URL for normal paths, so server-side calls like getSession() in src/lib/auth.ts hit the gateway directly instead of the Next rewrite path; in that context the incoming auth_token cookie is not forwarded, so authenticated users are treated as logged out (and in containerized deploys localhost:3001 also points at the dashboard container, not the gateway). Route server-side requests through /api/gateway/... or explicitly forward request cookies.

Useful? React with 👍 / 👎.

exp: Date.now() + 10 * 60 * 1000,
nonce: randomBytes(8).toString('hex'),
};
return Buffer.from(JSON.stringify(payload)).toString('base64url');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Sign TOTP temp tokens before trusting their payload

The temporary token is just base64url-encoded JSON and validateTempToken only decodes/parses it, so clients can forge {sub, exp} values without first completing password authentication. That lets an attacker bypass the password step for any TOTP-enabled account if they obtain a valid TOTP/backup code; this flow should use a signed token (JWT/HMAC) and verify signature and expiry before accepting sub.

Useful? React with 👍 / 👎.

}

async startContainer(containerId: string, actorId: string, actorEmail: string): Promise<void> {
await this.runDockerCommand(`docker start ${containerId}`);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Validate container IDs before executing docker shell commands

This command interpolates containerId directly into a shell string passed to exec, and the route params feeding it are not constrained to safe Docker ID/name characters. An authenticated operator can supply shell metacharacters in :id and trigger arbitrary host command execution; validate IDs with a strict regex and execute docker with argv-based APIs instead of a shell command string.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants