Personalizacion Avanzada

Por: Artiko
openspecpersonalizacionconfigrulesschemastestingseguridad

Personalizacion Avanzada

El problema

Ejecutas /opsx:propose add-user-auth y obtienes un plan con 6 tareas: crear modelo, crear servicio, crear controlador, crear rutas, crear middleware y configurar variables. Todo correcto, pero falta algo critico: no hay tareas de tests, ni validacion de inputs, ni consideraciones de seguridad.

El plan no es malo, es incompleto. OpenSpec genera artefactos basandose en el contexto que le proporcionas. Si no le dices que testing y seguridad son prioritarios, no los incluira.

Este capitulo explica como configurar OpenSpec para que por defecto cada plan incluya tests, seguridad y calidad.

Las 3 palancas de personalizacion

OpenSpec tiene 3 mecanismos que influyen en lo que la IA genera:

PalancaArchivoQue controla
Contextopenspec/config.yamlInformacion del proyecto que la IA recibe
Rulesopenspec/config.yamlRestricciones por tipo de artefacto
CLAUDE.mdCLAUDE.mdInstrucciones globales para Claude Code

Las 3 se complementan. context dice “que es este proyecto”, rules dice “que restricciones tiene cada artefacto” y CLAUDE.md dice “como debe comportarse la IA en general”.

config.yaml: Context

El campo context es lo que openspec instructions envia a la IA cuando genera artefactos. Aqui defines tu stack, convenciones y prioridades de calidad.

Antes (basico)

context: |
  Proyecto TypeScript con React y Express.

Despues (con calidad integrada)

context: |
  ## Stack
  - Runtime: Node.js 20, TypeScript 5.4 (strict mode)
  - Frontend: React 19, Vite 6, Tailwind CSS 4
  - Backend: Express 5, Prisma 6, PostgreSQL 16
  - Testing: Vitest (unit/integration), Playwright (e2e)
  - Linting: Biome (format + lint)
  - CI: Husky + lint-staged pre-commit

  ## Prioridades (en orden)
  1. Seguridad: validar inputs con zod, sanitizar datos, no exponer secretos
  2. Testing: todo codigo nuevo requiere tests unitarios minimo
  3. Performance: lazy loading, memoizacion, queries optimizadas
  4. Mantenibilidad: funciones < 30 lineas, archivos < 150 lineas

  ## Convenciones de testing
  - Tests unitarios junto al archivo fuente: `archivo.test.ts`
  - Mocks en `__mocks__/` del mismo directorio
  - Cobertura minima: 80% en lineas y branches
  - Naming: describe("NombreModulo") > it("should comportamiento")

  ## Seguridad obligatoria
  - Todo input del usuario se valida con zod antes de procesarse
  - Passwords hasheados con bcrypt (cost 12)
  - JWT con expiracion maxima de 1 hora
  - Rate limiting en endpoints publicos
  - Headers de seguridad con helmet
  - No logs de datos sensibles (passwords, tokens, PII)

La diferencia es que ahora la IA sabe que testing y seguridad son prioritarios. Cuando genere el design.md, considerara zod para validaciones. Cuando genere tasks.md, incluira tareas de tests.

config.yaml: Rules

Las rules son restricciones por tipo de artefacto. Son mas directivas que el context: le dicen a la IA que debe y que no debe hacer en cada artefacto especifico.

Rules para que tasks incluya tests

rules:
  tasks:
    - Incluir al menos una tarea de tests unitarios por cada modulo nuevo
    - Incluir tarea de test de integracion si el cambio toca API o BD
    - Las tareas de test van DESPUES de la implementacion del modulo
    - 'Formato: "Crear tests unitarios para [modulo] en [path].test.ts"'
    - Si el cambio modifica codigo existente, incluir tarea de actualizar tests

Rules para que design sea secure by default

rules:
  design:
    - "Validacion de inputs: especificar schema zod para cada endpoint/funcion publica"
    - "Autenticacion/autorizacion: especificar quien puede ejecutar cada accion"
    - "Datos sensibles: especificar como se almacenan, transmiten y loggean"
    - Si el cambio expone un endpoint, incluir seccion "Seguridad" en el design

Rules para specs con escenarios de seguridad

rules:
  specs:
    - Formato Given/When/Then obligatorio
    - Incluir escenario de input valido (happy path)
    - Incluir escenario de input invalido (tipos incorrectos, campos faltantes)
    - Incluir escenario de input malicioso (inyeccion SQL, XSS, path traversal)
    - Incluir escenario de limites (strings vacios, valores extremos, payloads grandes)

Rules para proposals acotados

rules:
  proposal:
    - Mantener bajo 500 palabras
    - "Secciones obligatorias: Motivacion, Alcance, Fuera de alcance, Riesgos"
    - En Riesgos, siempre considerar implicaciones de seguridad

config.yaml completo de ejemplo

schema: spec-driven

context: |
  ## Stack
  - Runtime: Node.js 20, TypeScript 5.4 (strict mode)
  - Frontend: React 19, Vite 6, Tailwind CSS 4
  - Backend: Express 5, Prisma 6, PostgreSQL 16
  - Testing: Vitest (unit/integration), Playwright (e2e)
  - Linting: Biome (format + lint)
  - CI: Husky + lint-staged pre-commit
  - Idioma: Espanol (artefactos en espanol)

  ## Prioridades
  1. Seguridad: validar inputs, sanitizar datos
  2. Testing: tests unitarios obligatorios para codigo nuevo
  3. Mantenibilidad: archivos < 150 lineas, funciones enfocadas

  ## Patrones de testing
  - Archivos test junto al fuente: modulo.test.ts
  - Vitest con coverage > 80%
  - Mocks con vi.mock() para dependencias externas

  ## Seguridad baseline
  - Validacion con zod en boundaries
  - bcrypt para passwords
  - Rate limiting en endpoints publicos

rules:
  proposal:
    - Maximo 500 palabras
    - Incluir seccion de Riesgos con consideraciones de seguridad
  specs:
    - Formato Given/When/Then obligatorio
    - Incluir escenarios de input invalido y malicioso para features con input del usuario
  design:
    - Incluir seccion "Seguridad" si el cambio expone endpoints o maneja datos del usuario
    - Especificar schemas de validacion (zod) para cada boundary
  tasks: |
    OBLIGATORIO:
    - Incluir tarea de tests unitarios por cada modulo nuevo
    - Incluir tarea de tests de integracion si toca API o BD
    - Incluir tarea de validacion de inputs si hay datos del usuario
    Las tareas de test van despues de implementar el modulo correspondiente.

El efecto en la generacion

Con esta configuracion, al ejecutar /opsx:propose add-user-auth, las tareas generadas se veran asi:

# Tasks: Add User Auth

- [ ] Crear schema de validacion con zod para registro y login
- [ ] Crear modelo User en Prisma con password hasheado
- [ ] Crear tests unitarios para el modelo User
- [ ] Crear AuthService con registro, login y verificacion JWT
- [ ] Crear tests unitarios para AuthService
- [ ] Crear middleware de autenticacion con verificacion JWT
- [ ] Crear tests unitarios para auth middleware
- [ ] Crear rutas POST /auth/register y POST /auth/login
- [ ] Crear tests de integracion para endpoints de auth
- [ ] Configurar rate limiting en rutas de auth
- [ ] Agregar headers de seguridad con helmet

Comparalo con el plan sin reglas: 6 tareas sin tests ni seguridad. Ahora tiene 11 tareas con tests intercalados y seguridad integrada.

CLAUDE.md como refuerzo

CLAUDE.md complementa a config.yaml. Mientras config.yaml influye solo en artefactos de OpenSpec, CLAUDE.md influye en todo lo que hace Claude Code, incluyendo cuando implementa con /opsx:apply.

# Prioridades
1. Seguridad: Validar inputs, sanitizar datos, no exponer secretos
2. Testing: Todo codigo nuevo requiere tests unitarios
3. Mantenibilidad: Funciones < 30 lineas, archivos < 150 lineas

# Testing
- Crear test file junto al modulo: modulo.test.ts
- Usar describe/it con nombres descriptivos
- Mockear dependencias externas, no la implementacion interna
- Coverage minimo: 80% lineas y branches

# Seguridad
- Validar todo input del usuario con zod
- No loggear datos sensibles
- Passwords con bcrypt, JWT con expiracion

Con esto, cuando /opsx:apply ejecuta las tareas, la IA sigue estas instrucciones al escribir el codigo real. El config.yaml asegura que las tareas existan; el CLAUDE.md asegura que la implementacion cumpla los estandares.

Schemas personalizados

Si el schema spec-driven (proposal → specs → design → tasks) no encaja con tu flujo, puedes crear uno propio.

Fork de un schema existente

openspec schema fork spec-driven secure-driven

Esto crea una copia del schema en openspec/schemas/secure-driven/ que puedes modificar:

Usar el schema nuevo

# openspec/config.yaml
schema: secure-driven

Crear schema desde cero

openspec schema init minimal --artifacts "tasks" --default

Esto crea un schema que solo genera tasks.md, sin proposal, specs ni design. Util para cambios pequenos donde la planificacion completa es innecesaria.

Orden de resolucion de schemas

Cuando ejecutas un comando de OpenSpec, el sistema determina que schema usar siguiendo una cadena de prioridad de 4 niveles:

PrioridadFuenteEjemplo
1 (maxima)Flag en CLIopenspec new --schema minimal mi-cambio
2Metadata del changeCampo schema: en el change activo
3config.yamlschema: spec-driven en la configuracion
4 (minima)Default del sistemaspec-driven (schema por defecto)

El nivel 1 siempre gana. Si no se especifica flag, se busca en el change actual. Si el change no tiene schema, se usa config.yaml. Si config.yaml tampoco lo define, se usa spec-driven.

Para diagnosticar que schema esta usando OpenSpec en un momento dado:

openspec schema which

Esto muestra el schema activo y de donde viene (CLI, change, config o default). Util cuando un cambio genera artefactos inesperados y sospechas que esta usando el schema incorrecto.

Validacion y depuracion de schemas

Despues de crear o modificar un schema custom, validalo antes de usarlo:

openspec schema validate mi-workflow

Este comando detecta:

Para ver todos los schemas disponibles y su estado:

openspec schema which --all

Esto lista los schemas built-in y los custom, indicando cual esta activo actualmente.

Cuando validar: siempre que crees un schema nuevo con init, hagas fork con fork, o modifiques manualmente los archivos de un schema existente.

Templates: guiando la generacion

Los templates son archivos markdown dentro del schema que definen la estructura que la IA debe seguir al generar cada artefacto. Son el mecanismo mas potente de personalizacion porque controlan directamente el formato del output.

Estructura de un template

Cada template usa section headers para definir las secciones del artefacto y HTML comments como instrucciones para la IA:

# {change_title}

## Motivacion
<!-- Explicar el problema que resuelve este cambio en 2-3 parrafos -->

## Alcance
<!-- Lista de componentes afectados -->

## Fuera de alcance
<!-- Que NO se va a hacer en este cambio -->

La IA recibe este template y lo usa como guia para generar el contenido, respetando las secciones y siguiendo las instrucciones en los comments.

Campos del schema que controlan templates

CampoQue hace
idIdentificador unico del artefacto (ej: tasks, design)
generatesArchivo de salida (ej: tasks.md, design.md)
templateRuta al archivo de template dentro del schema
instructionInstruccion adicional que la IA recibe al generar este artefacto
requiresLista de artefactos que deben existir antes de generar este

Ejemplo: template custom para tasks con tests obligatorios

# Tasks: {change_title}

## Implementacion
<!-- Tareas de implementacion del cambio -->

## Testing
<!-- OBLIGATORIO: al menos una tarea de test por cada modulo nuevo -->
<!-- Formato: "Crear tests [tipo] para [modulo] en [path].test.ts" -->

## Validacion
<!-- Tareas de verificacion final: lint, build, integracion -->

Con este template, la IA siempre genera secciones separadas para implementacion, testing y validacion. No puede omitir la seccion de testing porque el template la define explicitamente.

Templates vs Rules

AspectoTemplatesRules
Que sonArchivos de estructuraTexto de restricciones
Como actuanDefinen el formato del outputDefinen que incluir/excluir en el contenido
Donde vivenDirectorio del schemaconfig.yaml campo rules
Ejemplo”El artefacto tiene secciones: Motivacion, Alcance, Riesgos""Incluir consideraciones de seguridad en Riesgos”

Usa templates cuando quieras controlar la estructura. Usa rules cuando quieras controlar el contenido dentro de esa estructura. Combinados, dan control total sobre lo que genera OpenSpec.

Resumen


← Capitulo 11: Roadmap | Capitulo 13: Integracion con Herramientas de Calidad →