{"id":51317866,"url":"https://github.com/ajmelian/spec_template","last_synced_at":"2026-07-01T09:31:03.466Z","repository":{"id":367760879,"uuid":"1281362654","full_name":"ajmelian/spec_template","owner":"ajmelian","description":"Plantilla genérica para documentar cualquier proyecto con desarrollo dirigido por especificación (SDD): primero se escribe la spec, luego el plan, luego las tareas, y solo entonces se toca el código.","archived":false,"fork":false,"pushed_at":"2026-06-27T13:48:21.000Z","size":60,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-27T15:10:15.944Z","etag":null,"topics":["sdd","spec-driven-development","template"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ajmelian.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-26T13:33:16.000Z","updated_at":"2026-06-27T13:48:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ajmelian/spec_template","commit_stats":null,"previous_names":["ajmelian/spec_template"],"tags_count":null,"template":true,"template_full_name":null,"purl":"pkg:github/ajmelian/spec_template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajmelian%2Fspec_template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajmelian%2Fspec_template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajmelian%2Fspec_template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajmelian%2Fspec_template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ajmelian","download_url":"https://codeload.github.com/ajmelian/spec_template/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajmelian%2Fspec_template/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35001648,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["sdd","spec-driven-development","template"],"created_at":"2026-07-01T09:31:02.594Z","updated_at":"2026-07-01T09:31:03.447Z","avatar_url":"https://github.com/ajmelian.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Plantilla SDD profesional para APIs y aplicaciones online PHP\n\nEsta plantilla proporciona una estructura de documentación técnica para trabajar con **Spec-Driven Development (SDD)** en proyectos de aplicaciones online y APIs, especialmente en entornos PHP, CodeIgniter 4, MySQL/MariaDB y desarrollo asistido por IA.\n\nEl objetivo de la plantilla no es generar código directamente, sino crear una **fuente de verdad técnica** que gobierne el desarrollo: primero se documenta la intención, después se define el plan, luego se desglosan las tareas y finalmente se implementa y verifica.\n\nLa carpeta principal que se debe incorporar al proyecto es:\n\n```text\nspec/\n```\n\nEl directorio `spec/` contiene todos los artefactos SDD. El resto del proyecto debe contener el código real de la aplicación, sus dependencias, configuración, tests y documentación operativa propia.\n\n## Autoría\n\n**Autor principal:** Aythami Melian Perdomo  \n**Perfil profesional:** Ingeniero de Software PHP especializado en aplicaciones online, APIs, desarrollo seguro, DevSecOps y Spec-Driven Development.  \n**Asistencia técnica:** plantilla elaborada con apoyo de IA generativa bajo dirección, revisión y criterio técnico del autor.  \n**Versión de la plantilla:** 1.0.2  \n**Fecha:** 2026-06-27\n\nSalvo que el proyecto defina otra licencia específica, esta plantilla se entrega como base reutilizable, modificable y adaptable a proyectos propios o profesionales, manteniendo la atribución de autoría cuando se distribuya como plantilla independiente.\n\n## Principio de diseño\n\nEsta plantilla está pensada para trabajar en modo **spec-anchored**:\n\n1. La especificación se crea antes del código.\n2. La especificación se mantiene viva durante el desarrollo.\n3. Cualquier cambio funcional, técnico o de seguridad relevante debe reflejarse primero en `spec/`.\n4. El código se considera un artefacto derivado de la especificación.\n5. La validación se realiza contra criterios de aceptación, pruebas, gates de calidad y revisión de seguridad.\n\nEste enfoque reduce ambigüedad, pérdida de contexto, cambios invisibles de rumbo, deuda cognitiva y comportamiento indeterminado de los agentes de IA.\n\n## Qué incluye la plantilla\n\nLa plantilla contiene únicamente documentación SDD. No incluye `AGENTS.md`, `.opencode/`, comandos personalizados, configuración de IDE ni arneses de agente.\n\nEsto es deliberado.\n\nAl ejecutar `/init` en OpenCode, el agente debe leer el proyecto real, analizar el código existente, detectar el stack efectivo y generar su propio `AGENTS.md`. Si la plantilla incluyera un `AGENTS.md` genérico, podría contaminar el arnés del proyecto con reglas no ajustadas al código real.\n\n## Estructura\n\n```text\nspec/\n├── README.md\n├── constitution/\n│   ├── mission.md\n│   ├── tech-stack.md\n│   ├── coding-standards.md\n│   ├── security.md\n│   ├── quality-gates.md\n│   ├── git-workflow.md\n│   ├── documentation.md\n│   ├── roadmap.md\n│   └── glossary.md\n├── architecture/\n│   ├── overview.md\n│   ├── data-model.md\n│   ├── api-contract.md\n│   ├── integrations.md\n│   ├── deployment.md\n│   └── decisions/\n│       └── ADR-000-template.md\n├── api/\n│   └── openapi.yaml\n├── features/\n│   └── NNN-nombre-feature/\n│       ├── spec.md\n│       ├── plan.md\n│       ├── tasks.md\n│       ├── test-plan.md\n│       ├── security-review.md\n│       ├── verification.md\n│       ├── traceability.md\n│       └── release-notes.md\n├── testing/\n│   └── test-strategy.md\n├── operations/\n│   ├── deployment-runbook.md\n│   ├── rollback-plan.md\n│   └── observability.md\n└── risk/\n    └── risk-register.md\n```\n\n## Finalidad de cada bloque\n\nLos siguientes ejemplos usan como referencia una aplicación online realista denominada **Portal de Incidencias**, desarrollada con **PHP**, **CodeIgniter 4**, **MySQL**, **PHPUnit**, **HTML5**, **Bootstrap 5**, repositorio en **GitHub** y despliegue al servidor de desarrollo mediante **SFTP**.\n\nLa aplicación de ejemplo permite que usuarios autenticados registren incidencias, adjunten información básica, consulten el estado de sus tickets y que perfiles internos gestionen la resolución.\n\n### `spec/constitution/`\n\nDefine las reglas estables del proyecto. Debe completarse al inicio y modificarse poco.\n\nContiene la misión del producto, stack técnico, estándares de código, criterios de seguridad, gates de calidad, flujo Git, reglas de documentación, roadmap y glosario.\n\nLa constitución manda sobre las features. Si una feature necesita romper una regla de `constitution/`, primero debe justificarse con una decisión de arquitectura en `architecture/decisions/`.\n\n**Ejemplo aplicado:**\n\nEn el proyecto **Portal de Incidencias**, `constitution/` definiría que la aplicación se desarrolla en PHP con CodeIgniter 4, que la base de datos es MySQL, que el repositorio oficial está en GitHub, que las pruebas unitarias se ejecutan con PHPUnit, que la subida al servidor de desarrollo se realiza por SFTP y que el frontend se implementa con HTML5 y Bootstrap 5.\n\nEjemplo de contenido esperado:\n\n```text\nmission.md\n- Producto: Portal de Incidencias.\n- Usuarios: empleados, técnicos de soporte y administradores.\n- Objetivo: registrar, consultar y resolver incidencias internas.\n- Exclusiones: no incluye chat en tiempo real ni sistema avanzado de SLA en la primera versión.\n\ntech-stack.md\n- Backend: PHP 8.x + CodeIgniter 4.\n- Base de datos: MySQL.\n- Repositorio: GitHub.\n- Despliegue desarrollo: SFTP a dev.incidencias.example.com.\n- Testing: PHPUnit.\n- Frontend: HTML5 + Bootstrap 5.\n\nquality-gates.md\n- vendor/bin/phpunit debe finalizar correctamente.\n- No se acepta una feature sin validación backend.\n- No se acepta un endpoint nuevo sin actualizar OpenAPI.\n- No se suben ficheros .env al repositorio.\n```\n\n### `spec/architecture/`\n\nDocumenta cómo está construido el sistema.\n\nIncluye visión de arquitectura, modelo de datos, contrato API, integraciones, despliegue y decisiones ADR. Debe servir para que un ingeniero o un agente de IA entienda el sistema antes de modificarlo.\n\n**Ejemplo aplicado:**\n\nEn el **Portal de Incidencias**, `architecture/` describiría una arquitectura MVC propia de CodeIgniter 4, separando controladores, modelos, entidades, servicios, validadores, vistas HTML5/Bootstrap 5 y endpoints API.\n\nEjemplo de contenido esperado:\n\n```text\noverview.md\n- app/Controllers/Web/: controladores para pantallas HTML.\n- app/Controllers/Api/V1/: controladores REST.\n- app/Models/: acceso a tablas MySQL.\n- app/Entities/: representación de entidades de dominio.\n- app/Services/: lógica de negocio reutilizable.\n- app/Views/: vistas HTML5 con componentes Bootstrap 5.\n- public/assets/: CSS, JS e imágenes.\n\ndata-model.md\n- users: usuarios autenticados.\n- tickets: incidencias registradas.\n- ticket_comments: comentarios internos o visibles al usuario.\n- ticket_status_history: histórico de cambios de estado.\n\nintegrations.md\n- GitHub: repositorio fuente y pull requests.\n- SFTP: subida al servidor de desarrollo.\n- MySQL: persistencia principal.\n\ndeployment.md\n- Rama develop genera despliegue en servidor de desarrollo.\n- Subida por SFTP a /var/www/dev-incidencias/.\n- Migraciones ejecutadas con php spark migrate.\n```\n\nSi durante el desarrollo se decide cambiar de subida manual por SFTP a GitHub Actions con despliegue automatizado, esa decisión debería registrarse como un ADR, por ejemplo `ADR-001-automatizar-despliegue-desarrollo.md`.\n\n### `spec/api/`\n\nContiene el contrato OpenAPI.\n\nEn proyectos API, este contrato debe mantenerse alineado con el código. Toda feature que añada, modifique o elimine endpoints debe actualizar `spec/api/openapi.yaml` o justificar por qué no aplica.\n\n**Ejemplo aplicado:**\n\nEn el **Portal de Incidencias**, `api/openapi.yaml` documentaría los endpoints REST consumidos por el frontend, por integraciones internas o por herramientas externas.\n\nEjemplo de endpoints documentados:\n\n```text\nPOST   /api/v1/login\nGET    /api/v1/me\nGET    /api/v1/tickets\nPOST   /api/v1/tickets\nGET    /api/v1/tickets/{ticketId}\nPATCH  /api/v1/tickets/{ticketId}/status\nPOST   /api/v1/tickets/{ticketId}/comments\n```\n\nEjemplo de regla aplicable:\n\n```text\nSi se implementa TicketController::create(), debe existir en openapi.yaml:\n- path /api/v1/tickets\n- método POST\n- requestBody con title, description y priority\n- respuestas 201, 400, 401, 403 y 500\n- esquema TicketResponse\n```\n\nEsto evita que el código de la API evolucione por un lado y la documentación contractual por otro.\n\n### `spec/features/`\n\nContiene una carpeta por feature.\n\nCada feature debe documentarse como una unidad trazable, verificable y auditable. El patrón recomendado es:\n\n```text\nfeatures/001-login-api/\n├── spec.md\n├── plan.md\n├── tasks.md\n├── test-plan.md\n├── security-review.md\n├── verification.md\n├── traceability.md\n└── release-notes.md\n```\n\n**Ejemplo aplicado:**\n\nEn el **Portal de Incidencias**, una feature real podría ser `001-crear-ticket-incidencia`.\n\nEjemplo de uso:\n\n```text\nfeatures/001-crear-ticket-incidencia/spec.md\n- El usuario autenticado puede crear una incidencia indicando título, descripción y prioridad.\n- El sistema valida campos obligatorios en frontend y backend.\n- La incidencia queda registrada en MySQL con estado inicial \"abierta\".\n- El sistema devuelve una respuesta JSON con el identificador del ticket.\n\nfeatures/001-crear-ticket-incidencia/plan.md\n- Crear migración para tabla tickets si no existe.\n- Crear TicketModel.\n- Crear TicketEntity.\n- Crear TicketService.\n- Crear endpoint POST /api/v1/tickets.\n- Crear formulario HTML5 con Bootstrap 5.\n- Añadir validaciones en CodeIgniter 4.\n- Añadir pruebas PHPUnit.\n\nfeatures/001-crear-ticket-incidencia/tasks.md\n- TASK-001: crear migración de tickets.\n- TASK-002: crear modelo y entidad.\n- TASK-003: crear servicio de alta de incidencia.\n- TASK-004: crear endpoint API.\n- TASK-005: crear vista Bootstrap 5.\n- TASK-006: crear pruebas PHPUnit.\n- TASK-007: actualizar openapi.yaml.\n```\n\nEsta carpeta permitiría pedir al agente de IA una implementación acotada, con menor riesgo de que modifique partes no relacionadas del proyecto.\n\n### `spec/testing/`\n\nDefine la estrategia transversal de pruebas.\n\nDebe indicar tipos de pruebas, herramientas, cobertura mínima, datos de prueba, fixtures, pruebas de integración, pruebas de API, pruebas de regresión y responsabilidades.\n\n**Ejemplo aplicado:**\n\nEn el **Portal de Incidencias**, `testing/test-strategy.md` definiría que PHPUnit es la herramienta obligatoria para validar servicios, modelos, controladores y endpoints críticos.\n\nEjemplo de contenido esperado:\n\n```text\nHerramienta principal\n- PHPUnit ejecutado con vendor/bin/phpunit.\n\nBase de datos de pruebas\n- MySQL con esquema incidencias_test.\n- Datos de prueba cargados mediante seeds de CodeIgniter 4.\n\nTipos de prueba\n- Unitarias: TicketServiceTest, UserPermissionServiceTest.\n- Modelo: TicketModelTest.\n- API/Feature: CreateTicketApiTest, LoginApiTest.\n- Validación: campos obligatorios, longitud máxima, prioridad permitida.\n- Seguridad: usuario no autenticado, usuario sin permisos, payload inválido.\n\nComandos mínimos\n- composer install\n- php spark migrate --all\n- php spark db:seed TestSeeder\n- vendor/bin/phpunit\n```\n\nPara una feature como `001-crear-ticket-incidencia`, el plan de pruebas debería cubrir como mínimo creación correcta, error por falta de autenticación, error por datos inválidos y persistencia correcta en MySQL.\n\n### `spec/operations/`\n\nDefine cómo se despliega, observa y revierte el sistema.\n\nIncluye runbook de despliegue, plan de rollback y observabilidad mínima esperada: logs, métricas, trazas, alertas y eventos de auditoría.\n\n**Ejemplo aplicado:**\n\nEn el **Portal de Incidencias**, `operations/` documentaría el procedimiento operativo para subir la aplicación al servidor de desarrollo mediante SFTP.\n\nEjemplo de contenido esperado:\n\n```text\ndeployment-runbook.md\n- Rama origen: develop.\n- Repositorio: GitHub.\n- Servidor desarrollo: dev.incidencias.example.com.\n- Ruta remota: /var/www/dev-incidencias/.\n- Método de subida: SFTP.\n- Ficheros excluidos: .git/, .env, tests temporales, documentación privada.\n- Comando posterior: php spark migrate.\n- Verificación posterior: acceder a /health y ejecutar login de prueba.\n\nrollback-plan.md\n- Mantener copia de la release anterior en /var/www/dev-incidencias/releases/previous.\n- Antes de migrar MySQL, generar backup de la base de datos.\n- Si falla el smoke test, restaurar release anterior y backup si aplica.\n\nobservability.md\n- Revisar writable/logs/ de CodeIgniter 4.\n- Registrar errores de API sin exponer datos sensibles.\n- Registrar intentos fallidos de login.\n- Registrar creación y cambio de estado de tickets.\n```\n\nEste bloque evita que el despliegue dependa de memoria personal o instrucciones verbales.\n\n### `spec/risk/`\n\nContiene el registro de riesgos.\n\nDebe recoger riesgos técnicos, funcionales, operativos, legales y de seguridad, junto con impacto, probabilidad, mitigación, responsable y estado.\n\n**Ejemplo aplicado:**\n\nEn el **Portal de Incidencias**, `risk/risk-register.md` recogería riesgos propios de una aplicación PHP desplegada por SFTP, con MySQL y consumo mediante frontend HTML5/Bootstrap 5.\n\nEjemplo de riesgos:\n\n```text\nRISK-001: subida incompleta por SFTP\n- Impacto: alto.\n- Probabilidad: media.\n- Mitigación: checklist de despliegue, comparación de checksums y smoke test posterior.\n\nRISK-002: migración MySQL destructiva\n- Impacto: alto.\n- Probabilidad: baja/media.\n- Mitigación: backup previo, migraciones reversibles y revisión manual antes de ejecutar en desarrollo compartido.\n\nRISK-003: endpoint documentado de forma incompleta\n- Impacto: medio.\n- Probabilidad: media.\n- Mitigación: gate obligatorio de actualización de openapi.yaml.\n\nRISK-004: validación solo en frontend\n- Impacto: alto.\n- Probabilidad: media.\n- Mitigación: duplicar validaciones en CodeIgniter 4 y cubrirlas con PHPUnit.\n\nRISK-005: fuga de credenciales del entorno\n- Impacto: crítico.\n- Probabilidad: baja/media.\n- Mitigación: excluir .env del repositorio GitHub y de paquetes de despliegue, revisar permisos en servidor y no registrar secretos en logs.\n```\n\nEste registro debe revisarse cuando una feature introduzca cambios en autenticación, permisos, base de datos, despliegue, API o tratamiento de datos personales.\n\n## ¿Qué documentos se debe tener para rellenar los artefactos?\n\n### 1. Documentos técnicos necesarios para rellenar los artefactos obligatorios\n\nPara los artefactos obligatorios de arranque del proyecto, necesitaría estos documentos de entrada:\n\n| Documento técnico de entrada                                      | Artefactos que permite rellenar                                                       | Contenido mínimo necesario                                                                                                                                                                                                                                                                                                                                                                                                              |\n| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Documento de visión funcional del producto**                    | `spec/constitution/mission.md`                                                        | Qué se construye, para quién, problema que resuelve, propuesta de valor, límites del proyecto, exclusiones y KPIs. El propio `mission.md` pide descripción del producto, usuarios, cliente, equipo técnico, terceros integradores, propuesta de valor, límites e indicadores de éxito.                                                                                                                                                  |\n| **Documento de alcance funcional inicial / backlog inicial**      | `spec/constitution/mission.md`, `spec/constitution/roadmap.md`, primera feature       | Features previstas, prioridad, versión objetivo, qué entra en MVP, qué queda fuera, dependencias funcionales y entregas previstas.                                                                                                                                                                                                                                                                                                      |\n| **Documento de stack tecnológico y restricciones técnicas**       | `spec/constitution/tech-stack.md`                                                     | Lenguaje, framework, base de datos, servidor HTTP, gestor de dependencias, herramienta de testing, análisis estático, estilo de código, uso o no de contenedores, entornos y comandos reales del proyecto. El template ya espera lenguaje, framework, auth, BD, servidor, Composer, OpenAPI, PHPUnit, PHPStan/Psalm y PSR-12.                                                                                                           |\n| **Documento de estándares de desarrollo**                         | `spec/constitution/coding-standards.md`                                               | Convenciones de nombres, tipado, estructura de clases, separación por capas, PHPDoc/JSDoc/JavaDoc según stack, reglas de validación, gestión de errores y estilo de código. El artefacto exige criterios sobre funciones pequeñas, tipado, controladores finos, servicios testeables, documentación de funciones públicas y validación.                                                                                                 |\n| **Documento de seguridad base del proyecto**                      | `spec/constitution/security.md`, `quality-gates.md`, `security-review.md` de features | Autenticación, autorización, gestión de sesiones/tokens/API keys, rate limiting, CSRF, CORS, cabeceras de seguridad, clasificación de datos, secretos, logging seguro, OWASP y tratamiento de datos personales. El template contempla autenticación, autorización, APIs multi-cliente, validación, protecciones web/API, datos sensibles, secretos, logging y checklist OWASP.                                                          |\n| **Documento de Definition of Ready / Definition of Done técnico** | `spec/constitution/quality-gates.md`                                                  | Condiciones para empezar una feature, condiciones para cerrarla, pruebas mínimas, lint/análisis estático, actualización de OpenAPI, migraciones, seguridad, documentación, verificación y trazabilidad. La plantilla exige `spec.md`, criterios de aceptación, `plan.md`, `tasks.md` e identificación de impactos antes de implementar; y exige tests, OpenAPI, migraciones, seguridad, evidencias, trazabilidad y roadmap para cerrar. |\n| **Documento de flujo Git / gestión de ramas / PR**                | `spec/constitution/git-workflow.md`                                                   | Modelo GitFlow o trunk-based, ramas protegidas, formato de ramas, uso de Jira, formato de commits, reglas de PR, CI obligatorio y revisión humana. El template recomienda `main/master`, `develop`, `feature/JIRA-123`, `bugfix`, `hotfix`, `release`, y vinculación con Jira.                                                                                                                                                          |\n| **Documento de arquitectura inicial**                             | `spec/architecture/overview.md`                                                       | Tipo de sistema, módulos principales, capas, vista de contexto, dependencias externas, reglas de compatibilidad y límites arquitectónicos. El artefacto pide objetivo arquitectónico, vista de contexto, módulos, dependencias externas y reglas de compatibilidad.                                                                                                                                                                     |\n| **Documento de contrato API inicial**                             | `spec/api/openapi.yaml`, `spec/architecture/api-contract.md`                          | Nombre de API, versión, servidores, autenticación, endpoints iniciales, schemas, errores, paginación, versionado, headers y formato común de respuesta. El `openapi.yaml` ya parte de OpenAPI 3.0.3, servidores, tags, `/health`, security schemes y schemas base.                                                                                                                                                                      |\n| **Documento de primera feature / especificación funcional**       | `spec/features/NNN-nombre-feature/spec.md`                                            | Estado, Jira, responsable, fecha, versión objetivo, resumen, problema, objetivos, fuera de alcance, actores, historias de usuario, reglas de negocio, criterios de aceptación, impacto API, impacto datos, seguridad, no funcionales, suposiciones y dudas. Todo eso está previsto en el template de `spec.md`.                                                                                                                         |\n| **Documento de diseño técnico de la feature**                     | `spec/features/NNN-nombre-feature/plan.md`                                            | Enfoque técnico, módulos afectados, endpoints, validaciones, autorización, modelo de datos, errores, seguridad, pruebas, despliegue, riesgos, decisiones y dudas bloqueantes.                                                                                                                                                                                                                                                           |\n| **Documento de desglose de tareas técnicas**                      | `spec/features/NNN-nombre-feature/tasks.md`                                           | Tareas pequeñas, verificables y trazables: contrato, datos, implementación, pruebas, seguridad, calidad, cierre y PR. El template estructura tareas por preparación, contrato/datos, implementación, pruebas, seguridad/calidad y cierre.                                                                                                                                                                                               |\n| **Documento de plan de pruebas de feature**                       | `spec/features/NNN-nombre-feature/test-plan.md`                                       | Casos unitarios, integración/API, seguridad, datos de prueba, casos negativos obligatorios y comandos de ejecución.                                                                                                                                                                                                                                                                                                                     |\n| **Documento de revisión de seguridad de feature**                 | `spec/features/NNN-nombre-feature/security-review.md`                                 | Superficie de ataque, endpoints, formularios, ficheros, integraciones, datos sensibles, amenazas STRIDE simplificadas, checklist y hallazgos.                                                                                                                                                                                                                                                                                           |\n\n### 2. Documentos necesarios para rellenar el resto de artefactos\n\nPara completar el resto de artefactos de la plantilla, además de los anteriores, necesitaría estos documentos:\n\n| Documento técnico de entrada                     | Artefactos que permite rellenar                                            | Contenido necesario                                                                                                                                                                                                                     |\n| ------------------------------------------------ | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Modelo de datos / DER / diccionario de datos** | `spec/architecture/data-model.md`                                          | Entidades, tablas, campos, tipos, relaciones, índices, claves, timestamps, soft delete, migraciones, clasificación de datos y sensibilidad. El template pide convenciones, entidades, relaciones, migraciones y clasificación de datos. |\n| **Catálogo de integraciones externas**           | `spec/architecture/integrations.md`                                        | Servicios externos, tipo de integración, propietario, datos enviados/recibidos, criticidad, variables `.env`, timeouts, reintentos, fallback y degradación.                                                                             |\n| **Documento de arquitectura de despliegue**      | `spec/architecture/deployment.md`, `spec/operations/deployment-runbook.md` | Entornos, URLs, ramas, bases de datos, document root, permisos, TLS, variables, configuración, pasos de despliegue, backups, migraciones, cache, reinicios y smoke tests.                                                               |\n| **Runbook operativo de despliegue**              | `spec/operations/deployment-runbook.md`                                    | Precondiciones, release aprobada, CI verde, backup, ventana de mantenimiento, pasos de despliegue, smoke tests y evidencias.                                                                                                            |\n| **Plan de rollback / recuperación**              | `spec/operations/rollback-plan.md`, `release-notes.md`                     | Rollback de código, configuración, base de datos, feature flags, versión anterior, backups, migraciones reversibles, responsable y criterios de activación.                                                                             |\n| **Documento de observabilidad y auditoría**      | `spec/operations/observability.md`                                         | Logs, correlation ID, métricas, alertas, eventos de auditoría, errores 4xx/5xx, login fallidos, rate limits, latencia e integraciones externas.                                                                                         |\n| **Estrategia transversal de pruebas**            | `spec/testing/test-strategy.md`                                            | Niveles de prueba, unitarias, integración, contrato, seguridad, regresión, smoke, datos de prueba, mínimos por feature API y criterios de calidad.                                                                                      |\n| **Registro inicial de riesgos**                  | `spec/risk/risk-register.md`                                               | Riesgos técnicos, funcionales, operativos, legales y de seguridad, probabilidad, impacto, severidad, mitigación, responsable y estado. El artefacto exige precisamente esos campos.                                                     |\n| **Documento de decisiones arquitectónicas**      | `spec/architecture/decisions/ADR-000-template.md`                          | Contexto, decisión tomada, alternativas consideradas, ventajas, inconvenientes, motivo de descarte, consecuencias e impacto en código, seguridad, operaciones y documentación.                                                          |\n| **Glosario funcional/técnico del dominio**       | `spec/constitution/glossary.md`                                            | Términos de negocio, términos técnicos, definiciones, notas y fuentes. El template ya incluye términos como Cliente API, Tenant y Correlation ID.                                                                                       |\n| **Política de documentación del proyecto**       | `spec/constitution/documentation.md`                                       | Qué documentos se mantienen vivos, cuándo se actualizan, idioma, normas para README, `.env.example`, OpenAPI, arquitectura y documentación de features.                                                                                 |\n| **Roadmap de producto y releases**               | `spec/constitution/roadmap.md`                                             | Features hechas, en curso, siguientes, backlog, descartadas, responsables, bloqueos, fechas y versiones.                                                                                                                                |\n| **Evidencias de ejecución y QA**                 | `spec/features/NNN-nombre-feature/verification.md`, `traceability.md`      | Salida de tests, lint, análisis estático, pruebas manuales/API, evidencias, hallazgos, estado de criterios de aceptación, DoD, roadmap y release notes.                                                                                 |\n| **Matriz de trazabilidad**                       | `spec/features/NNN-nombre-feature/traceability.md`                         | Relación entre requisitos, criterios de aceptación, tareas, tests, ficheros, endpoints, OpenAPI, migraciones y rollback.                                                                                                                |\n| **Notas de release / entrega**                   | `spec/features/NNN-nombre-feature/release-notes.md`                        | Resumen de negocio, cambios técnicos, cambios API, migraciones, variables de entorno, riesgos de despliegue y rollback.                                                                                                                 |\n\n\n\n\n\n\n## Flujo recomendado para iniciar un proyecto\n\n1. Copiar la carpeta `spec/` en la raíz del proyecto.\n2. Rellenar `spec/constitution/mission.md`.\n3. Rellenar `spec/constitution/tech-stack.md`.\n4. Definir estándares en `coding-standards.md`.\n5. Definir seguridad base en `security.md`.\n6. Definir gates obligatorios en `quality-gates.md`.\n7. Documentar arquitectura inicial en `architecture/overview.md`.\n8. Documentar contrato API inicial en `api/openapi.yaml`.\n9. Crear la primera feature en `features/001-nombre-feature/`.\n10. Ejecutar `/init` en OpenCode cuando el proyecto ya tenga su estructura real y la carpeta `spec/`.\n\n## Flujo recomendado para una feature\n\nEl ejemplo de esta sección usa la feature `001-crear-ticket-incidencia` del **Portal de Incidencias**: una aplicación PHP con **CodeIgniter 4**, repositorio en **GitHub**, subida al servidor de desarrollo por **SFTP**, base de datos **MySQL**, pruebas con **PHPUnit** y frontend **HTML5 + Bootstrap 5**.\n\n### 1. Crear una carpeta nueva en `spec/features/`\n\nLa carpeta debe usar numeración incremental y un nombre corto, expresivo y estable.\n\nEjemplos de nomenclatura:\n\n```text\nspec/features/001-crear-ticket-incidencia/\nspec/features/002-listar-mis-incidencias/\nspec/features/003-cambiar-estado-incidencia/\nspec/features/004-comentar-incidencia/\n```\n\nEjemplo real aplicado:\n\n```text\nspec/features/001-crear-ticket-incidencia/\n├── spec.md\n├── plan.md\n├── tasks.md\n├── test-plan.md\n├── security-review.md\n├── verification.md\n├── traceability.md\n└── release-notes.md\n```\n\nLa carpeta `001-crear-ticket-incidencia` representa una única intención funcional: permitir que un usuario autenticado registre una incidencia desde el portal web o desde la API.\n\n### 2. Escribir `spec.md`\n\nEl fichero `spec.md` define qué debe hacer la feature, por qué existe y cómo se validará funcionalmente. No debe describir todavía el detalle técnico de implementación salvo que forme parte de una restricción funcional.\n\nDebe contener, como mínimo, estos campos.\n\n#### Objetivo\n\nDescribe la intención funcional de la feature.\n\nEjemplo:\n\n```text\nPermitir que un usuario autenticado cree una nueva incidencia indicando título, descripción y prioridad, quedando registrada en MySQL con estado inicial \"abierta\" y asociada al usuario creador.\n```\n\n#### Alcance\n\nDefine qué sí queda incluido.\n\nEjemplo:\n\n```text\n- Crear incidencia desde formulario web HTML5 con Bootstrap 5.\n- Crear incidencia mediante endpoint REST POST /api/v1/tickets.\n- Validar título, descripción y prioridad en frontend y backend.\n- Persistir la incidencia en la tabla tickets de MySQL.\n- Asociar la incidencia al usuario autenticado.\n- Devolver confirmación visual en frontend y respuesta JSON en API.\n```\n\n#### Fuera de alcance\n\nDefine qué no debe implementarse en esta feature, aunque esté relacionado.\n\nEjemplo:\n\n```text\n- No se implementa subida de adjuntos.\n- No se implementa asignación automática a técnicos.\n- No se implementa sistema de SLA.\n- No se implementan notificaciones por email.\n- No se implementa edición posterior de la incidencia.\n- No se implementa borrado lógico ni físico de incidencias.\n```\n\n#### Actores\n\nIdentifica los usuarios, sistemas o roles implicados.\n\nEjemplo:\n\n```text\n- Usuario autenticado: crea la incidencia.\n- Técnico de soporte: no interviene en esta feature, pero será consumidor posterior de la incidencia.\n- Administrador: no interviene en esta feature.\n- Sistema: valida, registra y devuelve el resultado de la operación.\n```\n\n#### Requisitos funcionales\n\nDeben ser numerados y verificables.\n\nEjemplo:\n\n```text\nREQ-001: El usuario autenticado puede acceder al formulario de creación de incidencia.\nREQ-002: El formulario debe solicitar título, descripción y prioridad.\nREQ-003: El sistema debe aceptar únicamente las prioridades baja, media y alta.\nREQ-004: Al enviar datos válidos, el sistema debe crear un registro en la tabla tickets.\nREQ-005: La incidencia debe quedar asociada al identificador del usuario autenticado.\nREQ-006: La incidencia debe crearse con estado inicial abierta.\nREQ-007: El endpoint POST /api/v1/tickets debe devolver HTTP 201 cuando la incidencia se crea correctamente.\nREQ-008: El endpoint debe devolver HTTP 400 cuando el payload sea inválido.\nREQ-009: El endpoint debe devolver HTTP 401 cuando el usuario no esté autenticado.\n```\n\n#### Requisitos no funcionales\n\nDeben indicar restricciones de seguridad, rendimiento, mantenibilidad, compatibilidad o calidad.\n\nEjemplo:\n\n```text\nNFR-001: La feature debe implementarse en PHP 8.x usando CodeIgniter 4.\nNFR-002: Las validaciones backend deben implementarse con los mecanismos de validación de CodeIgniter 4.\nNFR-003: El formulario debe ser HTML5 válido y usar componentes Bootstrap 5.\nNFR-004: La creación de la incidencia debe completarse en menos de 500 ms en entorno de desarrollo con MySQL local o equivalente.\nNFR-005: La feature debe cubrirse con pruebas PHPUnit.\nNFR-006: No se deben registrar en logs datos sensibles ni contenido completo de la descripción.\nNFR-007: El endpoint debe estar documentado en spec/api/openapi.yaml.\n```\n\n#### Criterios de aceptación\n\nDeben expresar condiciones observables para aceptar o rechazar la feature.\n\nEjemplo:\n\n```text\nAC-001: Dado un usuario autenticado, cuando accede a /tickets/new, entonces ve un formulario con título, descripción y prioridad.\nAC-002: Dado un usuario autenticado, cuando envía el formulario con datos válidos, entonces se crea una incidencia en MySQL con estado abierta.\nAC-003: Dado un usuario autenticado, cuando envía el formulario sin título, entonces se muestra un mensaje de validación y no se crea la incidencia.\nAC-004: Dado un cliente API autenticado, cuando envía POST /api/v1/tickets con payload válido, entonces recibe HTTP 201 y el identificador del ticket creado.\nAC-005: Dado un cliente API no autenticado, cuando envía POST /api/v1/tickets, entonces recibe HTTP 401.\nAC-006: Dado un cliente API autenticado, cuando envía una prioridad no permitida, entonces recibe HTTP 400.\nAC-007: La ejecución de vendor/bin/phpunit debe finalizar sin errores.\nAC-008: spec/api/openapi.yaml debe incluir el endpoint POST /api/v1/tickets con request, responses y esquema de salida.\n```\n\n### 3. Escribir `plan.md`\n\nEl fichero `plan.md` define cómo se implementará la feature. Debe traducir la intención de `spec.md` a decisiones técnicas concretas.\n\nDebe contener, como mínimo, estos campos.\n\n#### Enfoque técnico\n\nDescribe la estrategia de implementación.\n\nEjemplo:\n\n```text\nLa feature se implementará siguiendo el patrón MVC de CodeIgniter 4. Se añadirá un controlador web para mostrar y procesar el formulario HTML5/Bootstrap 5, un controlador API para aceptar POST /api/v1/tickets, un servicio TicketService para centralizar la lógica de creación, un modelo TicketModel para persistencia MySQL y una entidad TicketEntity para representar la incidencia.\n\nLa validación se aplicará en dos capas: restricciones HTML5 en frontend para mejorar UX y validación obligatoria backend en CodeIgniter 4 como control real de seguridad.\n```\n\n#### Archivos afectados\n\nLista los ficheros que se prevé crear o modificar.\n\nEjemplo:\n\n```text\napp/Controllers/Web/TicketController.php\napp/Controllers/Api/V1/TicketController.php\napp/Models/TicketModel.php\napp/Entities/TicketEntity.php\napp/Services/TicketService.php\napp/Database/Migrations/2026-06-27-000001_CreateTicketsTable.php\napp/Views/tickets/new.php\napp/Views/tickets/created.php\napp/Config/Routes.php\ntests/unit/Services/TicketServiceTest.php\ntests/feature/Api/CreateTicketApiTest.php\nspec/api/openapi.yaml\n```\n\n#### Endpoints\n\nDocumenta los endpoints afectados.\n\nEjemplo:\n\n```text\nPOST /api/v1/tickets\n\nRequest JSON:\n{\n  \"title\": \"No puedo acceder al panel\",\n  \"description\": \"Al iniciar sesión aparece un error 500.\",\n  \"priority\": \"alta\"\n}\n\nResponse 201:\n{\n  \"id\": 123,\n  \"title\": \"No puedo acceder al panel\",\n  \"priority\": \"alta\",\n  \"status\": \"abierta\",\n  \"createdAt\": \"2026-06-27T10:30:00+00:00\"\n}\n\nResponse 400:\n{\n  \"error\": \"validation_error\",\n  \"fields\": {\n    \"title\": \"El título es obligatorio.\"\n  }\n}\n```\n\nRutas web asociadas:\n\n```text\nGET  /tickets/new\nPOST /tickets\n```\n\n#### Modelo de datos\n\nDefine tablas, campos, relaciones e índices.\n\nEjemplo:\n\n```text\nTabla: tickets\n\nCampos:\n- id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY\n- user_id BIGINT UNSIGNED NOT NULL\n- title VARCHAR(150) NOT NULL\n- description TEXT NOT NULL\n- priority ENUM('baja', 'media', 'alta') NOT NULL DEFAULT 'media'\n- status ENUM('abierta', 'en_progreso', 'resuelta', 'cerrada') NOT NULL DEFAULT 'abierta'\n- created_at DATETIME NOT NULL\n- updated_at DATETIME NULL\n- deleted_at DATETIME NULL\n\nÍndices:\n- INDEX idx_tickets_user_id (user_id)\n- INDEX idx_tickets_status (status)\n- INDEX idx_tickets_priority (priority)\n\nRelaciones:\n- tickets.user_id referencia al usuario creador.\n```\n\n#### Servicios\n\nDefine la lógica de negocio que no debe quedar incrustada en controladores.\n\nEjemplo:\n\n```text\nTicketService::createTicket(int $userId, array $payload): TicketEntity\n\nResponsabilidades:\n- Normalizar datos de entrada.\n- Validar que la prioridad pertenece al catálogo permitido.\n- Crear la entidad TicketEntity.\n- Persistir mediante TicketModel.\n- Devolver la entidad creada.\n\nNo debe:\n- Leer directamente $_POST.\n- Renderizar vistas.\n- Construir respuestas HTTP.\n- Ejecutar consultas SQL manuales fuera de TicketModel.\n```\n\n#### Validaciones\n\nDefine reglas frontend y backend.\n\nEjemplo:\n\n```text\nFrontend HTML5:\n- title: required, maxlength=\"150\"\n- description: required, minlength=\"10\"\n- priority: select obligatorio con valores baja, media, alta\n\nBackend CodeIgniter 4:\n- title: required|min_length[5]|max_length[150]\n- description: required|min_length[10]|max_length[5000]\n- priority: required|in_list[baja,media,alta]\n\nNormalización:\n- title: trim.\n- description: trim.\n- priority: lowercase.\n```\n\n#### Migraciones\n\nDefine los cambios de base de datos.\n\nEjemplo:\n\n```text\nCrear migración:\napp/Database/Migrations/2026-06-27-000001_CreateTicketsTable.php\n\nComando de aplicación:\nphp spark migrate\n\nComando de reversión en desarrollo:\nphp spark migrate:rollback\n\nConsideraciones:\n- La migración no debe destruir datos existentes.\n- Si la tabla tickets ya existe, revisar compatibilidad antes de aplicar.\n- El rollback solo se ejecutará en desarrollo si no hay datos relevantes.\n```\n\n#### Riesgos técnicos\n\nIdentifica riesgos de implementación antes de tocar código.\n\nEjemplo:\n\n```text\nRISK-001: duplicar lógica de validación entre controlador web y controlador API.\nMitigación: centralizar reglas en TicketValidationRules o método privado reutilizable.\n\nRISK-002: crear incidencia sin usuario autenticado por error de control de sesión.\nMitigación: aplicar filtro de autenticación en rutas web y API.\n\nRISK-003: divergencia entre implementación y OpenAPI.\nMitigación: actualizar spec/api/openapi.yaml en la misma tarea que el endpoint.\n\nRISK-004: subida SFTP incompleta al servidor de desarrollo.\nMitigación: checklist de despliegue y smoke test posterior.\n```\n\n### 4. Escribir `tasks.md`\n\nEl fichero `tasks.md` convierte el plan en trabajo ejecutable. Las tareas deben ser pequeñas, verificables y vinculadas a requisitos o criterios de aceptación.\n\nDebe contener, como mínimo, estos campos.\n\n#### Tareas pequeñas\n\nEjemplo:\n\n```text\nTASK-001: Crear migración MySQL para tabla tickets.\nTASK-002: Crear TicketEntity.\nTASK-003: Crear TicketModel.\nTASK-004: Crear TicketService::createTicket().\nTASK-005: Crear controlador API app/Controllers/Api/V1/TicketController.php.\nTASK-006: Crear rutas API en app/Config/Routes.php.\nTASK-007: Crear controlador web app/Controllers/Web/TicketController.php.\nTASK-008: Crear vista app/Views/tickets/new.php con HTML5 y Bootstrap 5.\nTASK-009: Añadir validaciones frontend HTML5.\nTASK-010: Añadir validaciones backend CodeIgniter 4.\nTASK-011: Crear tests PHPUnit unitarios de TicketService.\nTASK-012: Crear tests PHPUnit de endpoint POST /api/v1/tickets.\nTASK-013: Actualizar spec/api/openapi.yaml.\nTASK-014: Ejecutar pruebas y documentar resultados en verification.md.\n```\n\n#### Verificables\n\nCada tarea debe indicar cómo se comprueba.\n\nEjemplo:\n\n```text\nTASK-001 se verifica ejecutando php spark migrate y comprobando que existe la tabla tickets en MySQL.\nTASK-004 se verifica con tests unitarios de TicketService.\nTASK-005 se verifica con test de API CreateTicketApiTest.\nTASK-008 se verifica accediendo a /tickets/new en servidor de desarrollo.\nTASK-013 se verifica revisando que openapi.yaml contiene POST /api/v1/tickets.\n```\n\n#### Marcables como completadas\n\nEjemplo:\n\n```text\n- [x] TASK-001: Crear migración MySQL para tabla tickets.\n- [x] TASK-002: Crear TicketEntity.\n- [x] TASK-003: Crear TicketModel.\n- [ ] TASK-004: Crear TicketService::createTicket().\n- [ ] TASK-005: Crear controlador API.\n- [ ] TASK-006: Crear rutas API.\n- [ ] TASK-007: Crear controlador web.\n- [ ] TASK-008: Crear vista Bootstrap 5.\n- [ ] TASK-009: Añadir validaciones frontend.\n- [ ] TASK-010: Añadir validaciones backend.\n- [ ] TASK-011: Crear tests unitarios.\n- [ ] TASK-012: Crear tests de API.\n- [ ] TASK-013: Actualizar OpenAPI.\n- [ ] TASK-014: Completar verification.md.\n```\n\n#### Asociables a requisitos y criterios de aceptación\n\nEjemplo:\n\n```text\nTASK-001 -\u003e REQ-004, REQ-006, AC-002\nTASK-004 -\u003e REQ-004, REQ-005, REQ-006, AC-002\nTASK-005 -\u003e REQ-007, REQ-008, REQ-009, AC-004, AC-005, AC-006\nTASK-008 -\u003e REQ-001, REQ-002, AC-001\nTASK-010 -\u003e REQ-003, AC-003, AC-006\nTASK-011 -\u003e NFR-005, AC-007\nTASK-013 -\u003e NFR-007, AC-008\n```\n\n### 5. Escribir `test-plan.md`\n\nEl fichero `test-plan.md` define cómo se validará la feature antes de cerrarla.\n\nDebe contener, como mínimo, estos campos.\n\n#### Tests unitarios\n\nEjemplo:\n\n```text\nTicketServiceTest::testCreateTicketWithValidPayloadCreatesTicket()\n- Valida que TicketService crea una incidencia con datos válidos.\n\nTicketServiceTest::testCreateTicketNormalizesPayload()\n- Valida trim de título y descripción.\n- Valida normalización lowercase de prioridad.\n\nTicketServiceTest::testCreateTicketRejectsInvalidPriority()\n- Valida que una prioridad fuera de catálogo no se acepta.\n```\n\n#### Tests de integración\n\nEjemplo:\n\n```text\nTicketModelTest::testTicketIsPersistedInMysql()\n- Inserta una incidencia en la base de datos de pruebas MySQL.\n- Comprueba que user_id, title, priority y status se guardan correctamente.\n\nTicketMigrationTest::testTicketsTableExists()\n- Comprueba que la migración crea la tabla tickets con los campos esperados.\n```\n\n#### Tests de API\n\nEjemplo:\n\n```text\nCreateTicketApiTest::testAuthenticatedUserCanCreateTicket()\n- POST /api/v1/tickets con token/sesión válida.\n- Espera HTTP 201.\n- Espera JSON con id, title, priority, status y createdAt.\n\nCreateTicketApiTest::testUnauthenticatedUserCannotCreateTicket()\n- POST /api/v1/tickets sin autenticación.\n- Espera HTTP 401.\n\nCreateTicketApiTest::testInvalidPayloadReturnsValidationError()\n- POST /api/v1/tickets sin title.\n- Espera HTTP 400.\n- Espera estructura JSON de errores por campo.\n```\n\n#### Casos negativos\n\nEjemplo:\n\n```text\n- title vacío: debe fallar.\n- title superior a 150 caracteres: debe fallar.\n- description inferior a 10 caracteres: debe fallar.\n- priority = urgente: debe fallar.\n- usuario no autenticado: debe fallar.\n- payload JSON malformado: debe fallar sin error 500.\n```\n\n#### Casos de seguridad\n\nEjemplo:\n\n```text\n- Intento de crear ticket sin sesión activa.\n- Intento de enviar HTML o JavaScript en title.\n- Intento de enviar payload con user_id manipulando el propietario.\n- Intento de superar longitud máxima en campos.\n- Validación de que no se escribe la descripción completa en logs.\n```\n\n#### Datos de prueba\n\nEjemplo:\n\n```text\nUsuario autenticado:\n- id: 10\n- email: usuario.demo@example.com\n- rol: user\n\nPayload válido:\n{\n  \"title\": \"No puedo acceder al panel\",\n  \"description\": \"Al iniciar sesión aparece un error 500.\",\n  \"priority\": \"alta\"\n}\n\nPayload inválido:\n{\n  \"title\": \"\",\n  \"description\": \"Error\",\n  \"priority\": \"urgente\"\n}\n\nBase de datos:\n- Esquema: incidencias_test\n- Seeds: UserSeeder, TicketSeeder opcional\n```\n\n### 6. Completar `security-review.md`\n\nEl fichero `security-review.md` documenta la revisión de seguridad específica de la feature.\n\nDebe contener, como mínimo, estos campos.\n\n#### Autenticación\n\nEjemplo:\n\n```text\nSEC-001: Las rutas GET /tickets/new y POST /tickets requieren usuario autenticado.\nSEC-002: El endpoint POST /api/v1/tickets requiere autenticación API o sesión válida según la estrategia definida en constitution/security.md.\nSEC-003: Si no existe usuario autenticado, la API devuelve HTTP 401 y la web redirige a login.\n```\n\n#### Autorización\n\nEjemplo:\n\n```text\nSEC-004: Un usuario solo puede crear incidencias en su propio nombre.\nSEC-005: El backend ignora cualquier user_id recibido en el payload.\nSEC-006: El user_id se obtiene exclusivamente desde la sesión o contexto autenticado.\n```\n\n#### Validación de entrada\n\nEjemplo:\n\n```text\nSEC-007: title se valida como obligatorio, longitud 5-150 y texto plano.\nSEC-008: description se valida como obligatoria, longitud 10-5000.\nSEC-009: priority se valida mediante lista cerrada: baja, media, alta.\nSEC-010: Los campos no reconocidos del payload no deben modificar propiedades internas.\n```\n\n#### Gestión de errores\n\nEjemplo:\n\n```text\nSEC-011: Los errores de validación devuelven HTTP 400 sin stack trace.\nSEC-012: Los errores de autenticación devuelven HTTP 401.\nSEC-013: Los errores internos devuelven mensaje genérico.\nSEC-014: Los logs técnicos no deben incluir secretos, cookies, tokens ni descripciones completas de incidencias.\n```\n\n#### Rate limiting\n\nEjemplo:\n\n```text\nSEC-015: POST /api/v1/tickets debe quedar protegido por rate limiting si la API queda expuesta fuera de la red interna.\nSEC-016: Límite inicial recomendado: 30 creaciones por usuario cada 10 minutos en desarrollo/preproducción.\nSEC-017: Los excesos devuelven HTTP 429.\n```\n\n#### CSRF/CORS si aplica\n\nEjemplo:\n\n```text\nSEC-018: El formulario web POST /tickets debe usar protección CSRF de CodeIgniter 4.\nSEC-019: El endpoint API no debe depender de CSRF si usa autenticación por token y no por cookie de navegador.\nSEC-020: CORS debe permitir únicamente los orígenes definidos en .env para entorno de desarrollo.\n```\n\n#### Tratamiento de datos sensibles\n\nEjemplo:\n\n```text\nSEC-021: La descripción de la incidencia puede contener información sensible introducida por el usuario.\nSEC-022: No se debe registrar description completa en logs.\nSEC-023: No se debe exponer información de otros usuarios en respuestas API.\nSEC-024: Los datos se almacenan en MySQL conforme a la política de retención del proyecto.\n```\n\n#### Riesgos OWASP\n\nEjemplo:\n\n```text\nAPI1 Broken Object Level Authorization:\n- Riesgo: manipulación de user_id para crear incidencias asociadas a otro usuario.\n- Control: user_id siempre se toma del contexto autenticado.\n\nAPI3 Broken Object Property Level Authorization:\n- Riesgo: asignación masiva de campos no permitidos.\n- Control: allowlist estricta de title, description y priority.\n\nAPI4 Unrestricted Resource Consumption:\n- Riesgo: creación masiva de tickets.\n- Control: rate limiting.\n\nAPI8 Security Misconfiguration:\n- Riesgo: CORS permisivo o errores con stack trace.\n- Control: configuración por entorno y errores genéricos en producción.\n\nXSS:\n- Riesgo: title o description con HTML/JavaScript.\n- Control: escape en vistas y validación/sanitización adecuada.\n```\n\n### 7. Mantener `traceability.md`\n\nEl fichero `traceability.md` permite auditar qué requisito queda cubierto por qué tarea, qué prueba y qué evidencia.\n\nDebe contener, como mínimo, estos campos.\n\n#### Requisito\n\nEjemplo:\n\n```text\nREQ-004: Al enviar datos válidos, el sistema debe crear un registro en la tabla tickets.\n```\n\n#### Criterio de aceptación\n\nEjemplo:\n\n```text\nAC-002: Dado un usuario autenticado, cuando envía el formulario con datos válidos, entonces se crea una incidencia en MySQL con estado abierta.\nAC-004: Dado un cliente API autenticado, cuando envía POST /api/v1/tickets con payload válido, entonces recibe HTTP 201 y el identificador del ticket creado.\n```\n\n#### Tarea\n\nEjemplo:\n\n```text\nTASK-001: Crear migración MySQL para tabla tickets.\nTASK-003: Crear TicketModel.\nTASK-004: Crear TicketService::createTicket().\nTASK-005: Crear controlador API.\n```\n\n#### Test\n\nEjemplo:\n\n```text\nTEST-001: TicketServiceTest::testCreateTicketWithValidPayloadCreatesTicket()\nTEST-004: CreateTicketApiTest::testAuthenticatedUserCanCreateTicket()\nTEST-005: TicketModelTest::testTicketIsPersistedInMysql()\n```\n\n#### Evidencia\n\nEjemplo:\n\n```text\nEVID-001: Captura o salida de vendor/bin/phpunit con resultado OK.\nEVID-002: Registro creado en tabla tickets del esquema incidencias_test.\nEVID-003: Respuesta HTTP 201 de POST /api/v1/tickets en entorno de desarrollo.\nEVID-004: Revisión de spec/api/openapi.yaml con path documentado.\n```\n\nEjemplo de tabla de trazabilidad:\n\n```text\n| Requisito | Criterio | Tarea | Test | Evidencia |\n|-----------|----------|-------|------|-----------|\n| REQ-004 | AC-002, AC-004 | TASK-001, TASK-003, TASK-004, TASK-005 | TEST-001, TEST-004, TEST-005 | EVID-001, EVID-002, EVID-003 |\n| REQ-003 | AC-006 | TASK-010 | TEST-003, TEST-006 | EVID-001 |\n| NFR-007 | AC-008 | TASK-013 | Revisión documental | EVID-004 |\n```\n\n### 8. Implementar el código\n\nLa implementación debe hacerse después de completar `spec.md`, `plan.md`, `tasks.md`, `test-plan.md` y `security-review.md`.\n\nEjemplo real de ejecución:\n\n```text\nRama GitHub:\nfeature/JIRA-123-crear-ticket-incidencia\n\nOrden recomendado:\n1. Crear migración MySQL.\n2. Crear entidad, modelo y servicio.\n3. Crear tests unitarios de servicio.\n4. Crear controlador API y tests de API.\n5. Crear controlador web y vista HTML5/Bootstrap 5.\n6. Actualizar rutas.\n7. Actualizar OpenAPI.\n8. Ejecutar PHPUnit.\n9. Subir rama a GitHub.\n10. Abrir Pull Request hacia develop.\n11. Desplegar en servidor de desarrollo por SFTP tras revisión o aprobación.\n```\n\nRegla operativa:\n\n```text\nNo se debe implementar una tarea que no esté descrita en tasks.md.\nSi durante la implementación aparece una necesidad nueva, primero se actualiza spec/ y después se modifica el código.\n```\n\n### 9. Completar `verification.md`\n\nEl fichero `verification.md` documenta cómo se ha comprobado que la feature cumple la especificación.\n\nDebe contener, como mínimo, estos campos.\n\n#### Comandos ejecutados\n\nEjemplo:\n\n```text\ncomposer install\nphp spark migrate --all\nphp spark db:seed TestSeeder\nvendor/bin/phpunit\nphp spark serve --host 0.0.0.0 --port 8080\n```\n\nComprobación manual en servidor de desarrollo tras subida SFTP:\n\n```text\nURL: https://dev.incidencias.example.com/tickets/new\nAcción: crear incidencia con usuario demo.\nResultado esperado: mensaje de confirmación y ticket visible en listado.\n```\n\n#### Resultado de tests\n\nEjemplo:\n\n```text\nPHPUnit 11.x\nTests: 18\nAssertions: 64\nFailures: 0\nErrors: 0\nSkipped: 0\nResultado: OK\n```\n\n#### Resultado de lint\n\nEjemplo:\n\n```text\nphp -l app/Services/TicketService.php: No syntax errors detected\nphp -l app/Controllers/Api/V1/TicketController.php: No syntax errors detected\nphp -l app/Controllers/Web/TicketController.php: No syntax errors detected\nphp -l app/Models/TicketModel.php: No syntax errors detected\nResultado: OK\n```\n\n#### Resultado de análisis estático\n\nEjemplo:\n\n```text\nHerramienta: PHPStan o Psalm, si el proyecto la tiene configurada.\nComando: vendor/bin/phpstan analyse app tests\nResultado: sin errores de nivel configurado.\n\nSi el proyecto todavía no tiene análisis estático:\nResultado: No aplica en esta versión.\nAcción pendiente: registrar incorporación de PHPStan/Psalm en roadmap técnico.\n```\n\n#### Evidencias\n\nEjemplo:\n\n```text\nEVID-001: salida completa de vendor/bin/phpunit almacenada en verification.md.\nEVID-002: captura o registro de respuesta HTTP 201 de POST /api/v1/tickets.\nEVID-003: comprobación en MySQL de registro creado en tickets.\nEVID-004: revisión de formulario /tickets/new en servidor de desarrollo.\nEVID-005: Pull Request en GitHub: feature/JIRA-123-crear-ticket-incidencia -\u003e develop.\nEVID-006: subida SFTP completada en /var/www/dev-incidencias/.\n```\n\n#### Incidencias detectadas\n\nEjemplo:\n\n```text\nINC-001: El formulario web permitía enviar descripción inferior a 10 caracteres.\nEstado: corregido.\nAcción: añadido minlength=\"10\" en HTML5 y regla min_length[10] en backend.\n\nINC-002: openapi.yaml no incluía respuesta 401.\nEstado: corregido.\nAcción: añadida respuesta 401 al endpoint POST /api/v1/tickets.\n```\n\n### 10. Completar `release-notes.md` si la feature llega a entrega\n\nEl fichero `release-notes.md` resume el cambio en lenguaje comprensible para revisión, despliegue o entrega.\n\nEjemplo:\n\n```text\n# Release notes — 001-crear-ticket-incidencia\n\n## Resumen\n\nSe añade la capacidad de crear incidencias desde el portal web y desde la API REST.\n\n## Cambios funcionales\n\n- Nuevo formulario web /tickets/new con HTML5 y Bootstrap 5.\n- Nuevo endpoint POST /api/v1/tickets.\n- Creación de incidencias con estado inicial abierta.\n- Validación de título, descripción y prioridad.\n\n## Cambios técnicos\n\n- Nueva tabla MySQL tickets.\n- Nuevo TicketModel.\n- Nuevo TicketEntity.\n- Nuevo TicketService.\n- Nuevos controladores Web y API.\n- Nuevas pruebas PHPUnit.\n- Contrato OpenAPI actualizado.\n\n## Seguridad\n\n- Requiere usuario autenticado.\n- user_id se obtiene del contexto autenticado, no del payload.\n- Validación backend obligatoria.\n- Protección CSRF en formulario web.\n- Rate limiting previsto para API expuesta.\n\n## Despliegue\n\n- Rama GitHub: feature/JIRA-123-crear-ticket-incidencia.\n- Destino inicial: servidor de desarrollo.\n- Método: SFTP.\n- Requiere ejecutar php spark migrate.\n\n## Rollback\n\n- Revertir Pull Request o commit en rama develop.\n- Restaurar versión anterior por SFTP.\n- Ejecutar php spark migrate:rollback solo si se confirma que no hay datos relevantes que conservar en desarrollo.\n\n## Verificación\n\n- PHPUnit completado sin errores.\n- Smoke test web completado.\n- Smoke test API completado.\n- OpenAPI revisado.\n```\n\n## Convención de trazabilidad\n\nSe recomienda usar identificadores estables:\n\n```text\nREQ-001    Requisito funcional\nNFR-001    Requisito no funcional\nAC-001     Criterio de aceptación\nTASK-001   Tarea técnica\nTEST-001   Caso de prueba\nSEC-001    Control de seguridad\nRISK-001   Riesgo\nADR-001    Decisión de arquitectura\n```\n\nEjemplo:\n\n```text\nREQ-001 -\u003e AC-001 -\u003e TASK-003 -\u003e TEST-002 -\u003e verification.md\n```\n\nEsta trazabilidad permite auditar si el código implementado responde realmente a la intención documentada.\n\n## Uso con OpenCode\n\nEl orden recomendado es:\n\n1. Incorporar `spec/` al proyecto.\n2. Rellenar como mínimo `mission.md`, `tech-stack.md`, `security.md` y `quality-gates.md`.\n3. Añadir o mantener el código real del proyecto.\n4. Ejecutar `/init`.\n5. Revisar el `AGENTS.md` generado por OpenCode.\n6. Ajustar manualmente `AGENTS.md` solo si alguna regla crítica no ha sido inferida correctamente.\n\nReglas operativas recomendadas:\n\n- Para tareas no triviales, usar modo Plan antes de permitir cambios.\n- No pedir implementación directa sin `spec.md`.\n- No aceptar cambios que no actualicen tests o verificación.\n- No cerrar una feature sin `verification.md`.\n- No modificar endpoints sin revisar `openapi.yaml`.\n- No aceptar excepciones de seguridad sin registrarlas en `security-review.md` o en un ADR.\n\n## Definition of Done técnica\n\nUna feature se considera terminada únicamente cuando cumple, como mínimo, estos puntos:\n\n- `spec.md` completado.\n- `plan.md` completado.\n- `tasks.md` completado.\n- `test-plan.md` completado.\n- `security-review.md` completado.\n- `traceability.md` actualizado.\n- Código implementado.\n- Tests ejecutados y superados.\n- Lint y análisis estático ejecutados.\n- OpenAPI actualizado si aplica.\n- Migraciones documentadas si aplica.\n- `verification.md` completado con evidencias.\n- `release-notes.md` completado si aplica.\n- `roadmap.md` actualizado.\n\n## Reglas de mantenimiento\n\nLa plantilla debe tratarse como documentación viva.\n\nNo debe convertirse en documentación decorativa. Si el código cambia y la especificación no, la especificación queda obsoleta. Si la especificación cambia y el código no, la implementación queda incompleta.\n\nLa regla base es:\n\n```text\nToda decisión relevante debe quedar reflejada en spec/.\n```\n\n## Qué no es esta plantilla\n\nEsta plantilla no es:\n\n- Un framework PHP.\n- Un generador de código.\n- Una estructura MVC.\n- Una configuración de OpenCode.\n- Un sustituto de tests.\n- Un sustituto de revisión humana.\n- Un documento comercial.\n\nEs una estructura de control técnico para dirigir el desarrollo con especificaciones, agentes de IA y validación humana.\n\n## Uso recomendado\n\nEsta plantilla es especialmente útil para:\n\n- APIs REST.\n- Backends PHP.\n- Aplicaciones CodeIgniter 4.\n- Integraciones con terceros.\n- Sistemas con requisitos de seguridad.\n- Proyectos con GitFlow y Jira.\n- Equipos que trabajan con agentes de IA.\n- Proyectos donde la trazabilidad técnica importa.\n\nTambién puede adaptarse a otros stacks si se modifican `tech-stack.md`, `coding-standards.md`, `quality-gates.md` y `security.md`.\n\n## Licencia y adaptación\n\nLa plantilla está pensada para ser copiada, modificada y adaptada por proyecto.\n\nAntes de usarla en producción, revisa todas las secciones marcadas como plantilla y elimina ejemplos que no apliquen al proyecto real.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fajmelian%2Fspec_template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fajmelian%2Fspec_template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fajmelian%2Fspec_template/lists"}