Este documento define los criterios mínimos que toda aplicación interna de Pampling
debe cumplir. Es la fuente de verdad que consulta el agente auditor del
Pampling Agent Cluster para revisar repositorios.
A toda aplicación que:
pmpServer (192.168.1.10) vía Coolify.pampling.Aplica tanto si la app la construyó una persona como si la construyó un agente.
https://wiki-mcp.pampl.ing/mcp/) y produce un informe de incumplimientosEl auditor admite dos modos:
security_critical: solo verifica items de severidad CRÍTICA y losfull: verifica todos los items. Pensado para revisiones periódicas.| Nivel | Significado | Acción esperada |
|---|---|---|
| 🔴 CRÍTICO | Riesgo de seguridad real, exposición de datos o credenciales | Bloqueante. Corregir antes de cualquier deploy. |
| 🟠 ALTO | Vulnerabilidad indirecta, mala práctica con consecuencias | Corregir antes del siguiente release. |
| 🟡 MEDIO | Problema de mantenibilidad u operativa | Corregir cuando se toque la zona afectada. |
| 🟢 BAJO / INFO | Estilo, limpieza, recomendaciones | Tener en cuenta, no bloqueante. |
Qué se valida: que no haya API keys, contraseñas, tokens de OAuth/JWT, cadenas
de conexión con credenciales, claves privadas SSH/TLS o similar en archivos
versionados.
Inaceptable:
ANTHROPIC_API_KEY = "sk-ant-api03-abc123..." # NO
DATABASE_URL = "postgresql://user:Pass123@host/db" # NO
Aceptable:
ANTHROPIC_API_KEY = os.environ["ANTHROPIC_API_KEY"]
DATABASE_URL = os.environ["DATABASE_URL"]
Las credenciales viven en variables de entorno (Coolify env vars en producción,
.env en local). El .env.example puede tener placeholders sin valor real.
.env en .gitignore y nunca commiteadoQué se valida:
.gitignore y contiene .env..env (sin extensión adicional) trackeados en el repo..env.example con placeholders.Qué se valida: que las queries con datos del usuario usen siempre parámetros,
no concatenación o f-strings.
Inaceptable:
cur.execute(f"SELECT * FROM users WHERE id = {user_id}") # NO
cur.execute("SELECT * FROM users WHERE name = '" + name + "'") # NO
Aceptable:
cur.execute("SELECT * FROM users WHERE id = %s", (user_id,))
cur.execute("SELECT * FROM users WHERE name = %s", (name,))
Aplica también a SQLAlchemy (text() con :param), Prisma, etc.
Qué se valida: que subprocess, os.system, eval, exec y similares no
reciban datos directos de requests sin validación estricta.
Inaceptable:
subprocess.run(f"convert {request.filename} out.png", shell=True) # NO
os.system("rm " + path_param) # NO
Aceptable:
subprocess.run(["convert", safe_filename, "out.png"], check=True)
# o validar contra allowlist antes
Qué se valida: rutas POST, PUT, PATCH y DELETE que modifican datos
sensibles deben tener algún tipo de control de acceso (token, sesión, IP allowlist
para herramientas internas).
Excepción: apps puramente internas que solo escuchan en LAN o detrás de VPN
pueden documentar la excepción en el CLAUDE.md del proyecto.
Qué se valida:
requirements.txt: cada paquete tiene == o ~= con versión, o el repo tienepoetry.lock, uv.lock).package.json: existe package-lock.json o yarn.lock.go.mod: existe go.sum.Inaceptable:
fastapi
uvicorn
psycopg2-binary
Aceptable:
fastapi==0.115.0
uvicorn==0.34.0
psycopg2-binary==2.9.10
* en producciónQué se valida: allow_origins en CORSMiddleware no es ["*"] salvo que se
documente explícitamente que es una API pública.
Inaceptable (en interno):
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True)
Aceptable:
app.add_middleware(
CORSMiddleware,
allow_origins=["https://stock-portal.pampl.ing"],
allow_credentials=True,
)
Qué se valida: el código no imprime/loggea passwords, tokens, headers
Authorization, contenido completo de request bodies con datos personales, etc.
Inaceptable:
logger.info(f"Login intent: {request.json}") # contiene password
print(f"Token: {auth_header}") # NO
CLAUDE.md del proyecto presenteQué se valida: existe CLAUDE.md en la raíz del repo, con como mínimo:
Sigue el Checklist: CLAUDE.md de proyecto.
.env.example presenteQué se valida: existe .env.example con todas las variables de entorno que la
app necesita, con placeholders (no valores reales).
ANTHROPIC_API_KEY=
DATABASE_URL=
Qué se valida: apps web exponen un endpoint /api/health (o equivalente
documentado) que devuelve 200 cuando el servicio está operativo. Coolify lo usa
para health checks de despliegue.
@app.get("/api/health")
async def health():
return {"status": "ok"}
Qué se valida: los endpoints no exponen tracebacks de Python al cliente y
manejan los errores esperables (registro no encontrado → 404, validación → 422,
permisos → 403, etc.).
FastAPI gestiona esto en gran medida con HTTPException. El auditor flaggea
endpoints donde hay accesos a BD/red sin ningún try/except ni manejo explícito.
Procfile o Dockerfile para CoolifyQué se valida: apps que se despliegan en Coolify tienen Procfile (Nixpacks)
o Dockerfile. La línea base de Pampling es Procfile:
web: uvicorn backend.main:app --host 0.0.0.0 --port 8000
create_app.mdQué se valida: apps Python+FastAPI siguen la estructura de carpetas estándar:
backend/
├── main.py
├── database.py
├── routers/
└── ...
frontend/
├── index.html
├── css/
└── js/
Si la app usa otro stack (Node, Go), tener una estructura consistente con el
ecosistema de ese stack.
Qué se valida: la IP del servidor (192.168.1.10), URLs de Coolify
(http://192.168.1.10:8000), workspace Bitbucket, etc. no aparecen hardcoded en
código de aplicación. Pueden estar en CLAUDE.md o ~/.claude/create_app.md,
pero no en backend/main.py.
Si el código necesita una de estas URLs, leerla de variable de entorno.
Qué se valida: el repo no tiene comentarios # TODO: o # FIXME: en código
de la rama main que indiquen funcionalidad incompleta crítica. Los TODOs en
ramas de feature están bien.
Qué se valida: convención Pampling — mensajes de usuario y comentarios
explicativos en español, identificadores (variables, funciones, clases) en inglés.
Qué se valida: que no haya .DS_Store, Thumbs.db, *.pyc, __pycache__/,
.venv/, node_modules/, archivos de IDE personales (.vscode/settings.json
con paths absolutos), logs, etc. en el repo.
Qué se valida: existe README.md con descripción accesible para gente
externa al equipo IA. No bloqueante si el CLAUDE.md ya lo cubre.
Estos requieren contexto humano y los reporta solo si los detecta por azar:
~/.claude/create_app.md si el item| Fecha | Cambio | Autor |
|---|---|---|
| 2026-04-30 | Versión inicial — 19 items | Equipo IA |