@saulwade/swl-ses 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +238 -0
- package/README.md +560 -0
- package/_userland/agentes/.gitkeep +0 -0
- package/_userland/habilidades/.gitkeep +0 -0
- package/agentes/.evolved.json +9 -0
- package/agentes/accesibilidad-wcag-swl.md +692 -0
- package/agentes/arquitecto-swl.md +238 -0
- package/agentes/auto-evolucion-swl.md +854 -0
- package/agentes/backend-api-swl.md +470 -0
- package/agentes/backend-csharp-swl.md +418 -0
- package/agentes/backend-go-swl.md +388 -0
- package/agentes/backend-java-swl.md +279 -0
- package/agentes/backend-node-swl.md +477 -0
- package/agentes/backend-python-swl.md +608 -0
- package/agentes/backend-rust-swl.md +362 -0
- package/agentes/backend-workers-swl.md +480 -0
- package/agentes/cloud-infra-swl.md +485 -0
- package/agentes/consolidador-swl.md +539 -0
- package/agentes/datos-swl.md +584 -0
- package/agentes/depurador-swl.md +349 -0
- package/agentes/devops-ci-swl.md +374 -0
- package/agentes/disenador-ui-swl.md +558 -0
- package/agentes/documentador-swl.md +343 -0
- package/agentes/evals/arquitecto-swl.evals.json +56 -0
- package/agentes/evals/auto-evolucion-swl.evals.json +68 -0
- package/agentes/evals/implementador-swl.evals.json +56 -0
- package/agentes/evals/orquestador-swl.evals.json +60 -0
- package/agentes/evals/perfilador-usuario-swl.evals.json +60 -0
- package/agentes/evals/red-team-swl.evals.json +59 -0
- package/agentes/evals/revisor-codigo-swl.evals.json +59 -0
- package/agentes/frontend-angular-swl.md +627 -0
- package/agentes/frontend-css-swl.md +720 -0
- package/agentes/frontend-react-swl.md +696 -0
- package/agentes/frontend-swl.md +500 -0
- package/agentes/frontend-tailwind-swl.md +830 -0
- package/agentes/implementador-swl.md +328 -0
- package/agentes/investigador-swl.md +430 -0
- package/agentes/investigador-ux-swl.md +500 -0
- package/agentes/llm-apps-swl.md +276 -0
- package/agentes/migrador-swl.md +417 -0
- package/agentes/mobile-android-swl.md +509 -0
- package/agentes/mobile-cross-swl.md +539 -0
- package/agentes/mobile-ios-swl.md +500 -0
- package/agentes/mobile-testing-swl.md +300 -0
- package/agentes/notificador-swl.md +916 -0
- package/agentes/observabilidad-swl.md +436 -0
- package/agentes/orquestador-swl.md +884 -0
- package/agentes/pagos-swl.md +283 -0
- package/agentes/perfilador-usuario-swl.md +306 -0
- package/agentes/planificador-swl.md +402 -0
- package/agentes/producto-prd-swl.md +587 -0
- package/agentes/red-team-swl.md +216 -0
- package/agentes/release-manager-swl.md +568 -0
- package/agentes/rendimiento-swl.md +714 -0
- package/agentes/resolutor-build-swl.md +243 -0
- package/agentes/revisor-angular-swl.md +276 -0
- package/agentes/revisor-codigo-swl.md +348 -0
- package/agentes/revisor-csharp-swl.md +262 -0
- package/agentes/revisor-go-swl.md +257 -0
- package/agentes/revisor-java-swl.md +255 -0
- package/agentes/revisor-kotlin-swl.md +271 -0
- package/agentes/revisor-nextjs-swl.md +279 -0
- package/agentes/revisor-php-swl.md +269 -0
- package/agentes/revisor-react-swl.md +276 -0
- package/agentes/revisor-rust-swl.md +344 -0
- package/agentes/revisor-seguridad-swl.md +390 -0
- package/agentes/revisor-swift-swl.md +266 -0
- package/agentes/revisor-typescript-swl.md +344 -0
- package/agentes/sre-swl.md +265 -0
- package/agentes/tdd-qa-swl.md +354 -0
- package/agentes/ux-disenador-swl.md +501 -0
- package/bin/lib/bot-comandos.js +1030 -0
- package/bin/lib/bot-discovery.js +182 -0
- package/bin/lib/bot-git.js +142 -0
- package/bin/swl-ses.js +325 -0
- package/bin/swl-telegram-bot.js +442 -0
- package/bin/swl-telegram-bot.plist +21 -0
- package/bin/swl-telegram-bot.service +14 -0
- package/comandos/swl/.evolved.json +23 -0
- package/comandos/swl/actualizar.md +174 -0
- package/comandos/swl/adoptar-proyecto.md +207 -0
- package/comandos/swl/aprender.md +701 -0
- package/comandos/swl/auditar-deps.md +134 -0
- package/comandos/swl/autoresearch.md +170 -0
- package/comandos/swl/ayuda.md +224 -0
- package/comandos/swl/brainstorm.md +50 -0
- package/comandos/swl/checkpoint.md +330 -0
- package/comandos/swl/compactar.md +283 -0
- package/comandos/swl/configurar-ci.md +227 -0
- package/comandos/swl/contexto.md +112 -0
- package/comandos/swl/contribuir.md +233 -0
- package/comandos/swl/crear-skill.md +292 -0
- package/comandos/swl/cron.md +196 -0
- package/comandos/swl/dashboard.md +146 -0
- package/comandos/swl/discutir-fase.md +230 -0
- package/comandos/swl/ejecutar-fase.md +135 -0
- package/comandos/swl/evaluar-skill.md +487 -0
- package/comandos/swl/evolucion-estado.md +142 -0
- package/comandos/swl/evolucionar.md +259 -0
- package/comandos/swl/exportar-vault.md +189 -0
- package/comandos/swl/gateway.md +158 -0
- package/comandos/swl/inbox.md +116 -0
- package/comandos/swl/instalar.md +220 -0
- package/comandos/swl/instintos.md +86 -0
- package/comandos/swl/mapear-codebase.md +312 -0
- package/comandos/swl/mcp-status.md +175 -0
- package/comandos/swl/metricas.md +270 -0
- package/comandos/swl/modelo.md +102 -0
- package/comandos/swl/notificaciones.md +396 -0
- package/comandos/swl/nuevo-proyecto.md +154 -0
- package/comandos/swl/planear-fase.md +221 -0
- package/comandos/swl/plugins.md +256 -0
- package/comandos/swl/reflect-skills.md +125 -0
- package/comandos/swl/release.md +217 -0
- package/comandos/swl/revisar-impacto.md +206 -0
- package/comandos/swl/revisar.md +330 -0
- package/comandos/swl/salud.md +363 -0
- package/comandos/swl/sesiones.md +200 -0
- package/comandos/swl/skill-search.md +113 -0
- package/comandos/swl/verificar.md +585 -0
- package/comandos/swl/wiki.md +620 -0
- package/contextos/dev.md +32 -0
- package/contextos/research.md +30 -0
- package/contextos/review.md +31 -0
- package/habilidades/accesibilidad-a11y/SKILL.md +201 -0
- package/habilidades/accesibilidad-a11y/evals/evals.json +56 -0
- package/habilidades/accesibilidad-a11y/recursos/ejemplos-y-checklist-completo.md +441 -0
- package/habilidades/agent-browser/SKILL.md +218 -0
- package/habilidades/agentes-como-servicio/SKILL.md +218 -0
- package/habilidades/ai-runtime-security/SKILL.md +273 -0
- package/habilidades/angular-avanzado/SKILL.md +164 -0
- package/habilidades/angular-avanzado/recursos/ejemplos-avanzados.md +219 -0
- package/habilidades/angular-moderno/SKILL.md +186 -0
- package/habilidades/angular-moderno/evals/evals.json +45 -0
- package/habilidades/angular-moderno/recursos/ejemplos-avanzados.md +106 -0
- package/habilidades/api-rest-diseno/SKILL.md +191 -0
- package/habilidades/api-rest-diseno/recursos/openapi-template.yaml +506 -0
- package/habilidades/api-rest-diseno/recursos/referencia-api.md +140 -0
- package/habilidades/aprendizaje-continuo/SKILL.md +151 -0
- package/habilidades/aprendizaje-continuo/evals/evals.json +53 -0
- package/habilidades/aprendizaje-continuo/recursos/referencia-instintos.md +290 -0
- package/habilidades/async-python/SKILL.md +149 -0
- package/habilidades/async-python/evals/evals.json +47 -0
- package/habilidades/async-python/recursos/patrones-y-ejemplos-completos.md +292 -0
- package/habilidades/auth-patrones/.evolved.json +9 -0
- package/habilidades/auth-patrones/SKILL.md +413 -0
- package/habilidades/auth-patrones/recursos/implementaciones-completas.md +229 -0
- package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -0
- package/habilidades/auto-evolucion-protocolo/evals/evals.json +55 -0
- package/habilidades/auto-evolucion-protocolo/recursos/referencia-completa.md +145 -0
- package/habilidades/autoresearch/SKILL.md +268 -0
- package/habilidades/autoresearch/evals/evals.json +41 -0
- package/habilidades/autoresearch/recursos/checklist-template.md +191 -0
- package/habilidades/autoresearch/scripts/calcular-score.js +88 -0
- package/habilidades/azure-cloud/SKILL.md +308 -0
- package/habilidades/azure-cloud/recursos/aks.md +327 -0
- package/habilidades/backend-mcp-servidor/SKILL.md +270 -0
- package/habilidades/backend-production-resilience/SKILL.md +288 -0
- package/habilidades/brainstorming/SKILL.md +295 -0
- package/habilidades/brainstorming/recursos/componentes-html.md +247 -0
- package/habilidades/build-errors-cpp/SKILL.md +270 -0
- package/habilidades/build-errors-csharp/SKILL.md +265 -0
- package/habilidades/build-errors-go/SKILL.md +306 -0
- package/habilidades/build-errors-java/SKILL.md +278 -0
- package/habilidades/build-errors-kotlin/SKILL.md +303 -0
- package/habilidades/build-errors-nextjs/SKILL.md +312 -0
- package/habilidades/build-errors-php/SKILL.md +270 -0
- package/habilidades/build-errors-python/SKILL.md +292 -0
- package/habilidades/build-errors-rust/SKILL.md +284 -0
- package/habilidades/build-errors-swift/SKILL.md +272 -0
- package/habilidades/build-errors-typescript/SKILL.md +369 -0
- package/habilidades/checklist-calidad/SKILL.md +271 -0
- package/habilidades/checklist-calidad/recursos/quality-report-template.md +148 -0
- package/habilidades/checklist-seguridad/SKILL.md +285 -0
- package/habilidades/checkpoints-verificacion/SKILL.md +298 -0
- package/habilidades/checkpoints-verificacion/recursos/checkpoint-templates.md +360 -0
- package/habilidades/ci-cd-pipelines/SKILL.md +157 -0
- package/habilidades/ci-cd-pipelines/recursos/github-actions-template.yaml +403 -0
- package/habilidades/ci-cd-pipelines/recursos/pipelines-completos.md +487 -0
- package/habilidades/cloud-aws/SKILL.md +142 -0
- package/habilidades/cloud-aws/recursos/servicios-aws-referencia.md +321 -0
- package/habilidades/compactacion-contexto/SKILL.md +247 -0
- package/habilidades/contenedores-docker/SKILL.md +137 -0
- package/habilidades/contenedores-docker/recursos/dockerfile-template.dockerfile +160 -0
- package/habilidades/contenedores-docker/recursos/ejemplos-y-configuraciones.md +327 -0
- package/habilidades/context-builder/SKILL.md +170 -0
- package/habilidades/control-profundidad/SKILL.md +128 -0
- package/habilidades/csharp-experto/SKILL.md +322 -0
- package/habilidades/csharp-patrones/SKILL.md +316 -0
- package/habilidades/csharp-testing/SKILL.md +286 -0
- package/habilidades/css-moderno/SKILL.md +166 -0
- package/habilidades/css-moderno/evals/evals.json +43 -0
- package/habilidades/css-moderno/recursos/ejemplos-y-patrones-completos.md +337 -0
- package/habilidades/datos-etl/SKILL.md +129 -0
- package/habilidades/datos-etl/recursos/implementaciones-completas.md +322 -0
- package/habilidades/dbml-experto/SKILL.md +339 -0
- package/habilidades/dbml-experto/evals/evals.json +56 -0
- package/habilidades/dependencias-auditoria/SKILL.md +320 -0
- package/habilidades/deprecacion-migracion/SKILL.md +169 -0
- package/habilidades/deprecacion-migracion/recursos/implementaciones-completas.md +220 -0
- package/habilidades/design-tokens/SKILL.md +158 -0
- package/habilidades/design-tokens/recursos/tokens-y-configuracion.md +363 -0
- package/habilidades/devsecops-pipeline-security/SKILL.md +309 -0
- package/habilidades/diagrama-arquitectura/SKILL.md +165 -0
- package/habilidades/diagrama-arquitectura/assets/template.html +276 -0
- package/habilidades/discutir-fase/SKILL.md +188 -0
- package/habilidades/diseno-herramientas-agente/SKILL.md +199 -0
- package/habilidades/diseno-responsivo/SKILL.md +186 -0
- package/habilidades/diseno-responsivo/recursos/ejemplos-layouts.md +156 -0
- package/habilidades/django-experto/SKILL.md +205 -0
- package/habilidades/django-experto/recursos/async-django.md +390 -0
- package/habilidades/django-experto/recursos/drf-patrones.md +438 -0
- package/habilidades/django-experto/recursos/orm-avanzado.md +382 -0
- package/habilidades/django-experto/recursos/referencia-completa.md +188 -0
- package/habilidades/django-experto/recursos/testing-django.md +415 -0
- package/habilidades/doc-sync/SKILL.md +280 -0
- package/habilidades/drift-detection/SKILL.md +179 -0
- package/habilidades/ejecutar-fase/SKILL.md +468 -0
- package/habilidades/estilo-sin-ai-isms/SKILL.md +775 -0
- package/habilidades/estilo-sin-ai-isms/evals/evals.json +63 -0
- package/habilidades/estilo-sin-ai-isms/scripts/detectar_aiisms.py +500 -0
- package/habilidades/estructura-proyecto-claude/SKILL.md +215 -0
- package/habilidades/estructura-proyecto-claude/recursos/claude-md-template.md +261 -0
- package/habilidades/estructura-proyecto-claude/recursos/configuracion-y-extensiones.md +176 -0
- package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +289 -0
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +77 -0
- package/habilidades/estructura-proyecto-claude/recursos/variantes-por-stack.md +177 -0
- package/habilidades/evaluacion-agentes/SKILL.md +314 -0
- package/habilidades/event-driven/SKILL.md +153 -0
- package/habilidades/event-driven/recursos/implementaciones-completas.md +423 -0
- package/habilidades/extraccion-documentos/SKILL.md +221 -0
- package/habilidades/extractor-de-aprendizajes/.evolved.json +9 -0
- package/habilidades/extractor-de-aprendizajes/SKILL.md +311 -0
- package/habilidades/extractor-de-aprendizajes/evals/evals.json +55 -0
- package/habilidades/fastapi-experto/SKILL.md +221 -0
- package/habilidades/fastapi-experto/recursos/async-patterns.md +438 -0
- package/habilidades/fastapi-experto/recursos/dependency-injection.md +330 -0
- package/habilidades/fastapi-experto/recursos/referencia-completa.md +79 -0
- package/habilidades/fastapi-experto/recursos/testing-httpx.md +420 -0
- package/habilidades/filament-admin/SKILL.md +290 -0
- package/habilidades/frontend-avanzado/SKILL.md +257 -0
- package/habilidades/frontend-avanzado/recursos/apis-nativas-ejemplos.md +341 -0
- package/habilidades/gcp-cloud/SKILL.md +260 -0
- package/habilidades/gcp-cloud/recursos/gke.md +234 -0
- package/habilidades/gcp-cloud/recursos/terraform-gcp.md +307 -0
- package/habilidades/generacion-mermaid/SKILL.md +229 -0
- package/habilidades/git-worktrees-paralelo/SKILL.md +270 -0
- package/habilidades/go-experto/SKILL.md +305 -0
- package/habilidades/go-patrones/SKILL.md +299 -0
- package/habilidades/go-testing/SKILL.md +291 -0
- package/habilidades/graphql-experto/SKILL.md +323 -0
- package/habilidades/guardrail-semantico/SKILL.md +282 -0
- package/habilidades/harness-claude-code/SKILL.md +299 -0
- package/habilidades/iam-secretos/SKILL.md +265 -0
- package/habilidades/iam-secretos/recursos/implementaciones-completas.md +356 -0
- package/habilidades/infra-github-actions/SKILL.md +166 -0
- package/habilidades/instalar-sistema/.evolved.json +9 -0
- package/habilidades/instalar-sistema/SKILL.md +221 -0
- package/habilidades/java-experto/SKILL.md +290 -0
- package/habilidades/java-patrones/SKILL.md +275 -0
- package/habilidades/java-testing/SKILL.md +288 -0
- package/habilidades/kotlin-compose/SKILL.md +278 -0
- package/habilidades/kotlin-compose/recursos/animaciones-performance.md +93 -0
- package/habilidades/kotlin-experto/SKILL.md +318 -0
- package/habilidades/kotlin-testing/SKILL.md +267 -0
- package/habilidades/kotlin-testing/recursos/testing-avanzado.md +74 -0
- package/habilidades/kubernetes-orquestacion/SKILL.md +152 -0
- package/habilidades/kubernetes-orquestacion/recursos/manifiestos-completos.md +452 -0
- package/habilidades/langchain-langraph/SKILL.md +386 -0
- package/habilidades/langchain-langraph/recursos/evaluacion-rag.md +321 -0
- package/habilidades/langchain-langraph/recursos/rag-maturity-model.md +225 -0
- package/habilidades/langchain-langraph/recursos/vectorstores.md +306 -0
- package/habilidades/legacy-code-rescue/SKILL.md +267 -0
- package/habilidades/likec4-experto/SKILL.md +412 -0
- package/habilidades/likec4-experto/evals/evals.json +69 -0
- package/habilidades/manejo-errores/.evolved.json +9 -0
- package/habilidades/manejo-errores/SKILL.md +407 -0
- package/habilidades/manejo-errores/recursos/implementaciones-completas.md +248 -0
- package/habilidades/mapear-codebase/SKILL.md +275 -0
- package/habilidades/memoria-busqueda/SKILL.md +194 -0
- package/habilidades/memoria-busqueda/evals/evals.json +44 -0
- package/habilidades/meta-skills-estandar/SKILL.md +298 -0
- package/habilidades/meta-skills-estandar/recursos/anti-patrones-y-leyes.md +205 -0
- package/habilidades/meta-skills-estandar/recursos/frameworks-seguridad.md +107 -0
- package/habilidades/meta-skills-estandar/recursos/idiomas-framework.md +60 -0
- package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +163 -0
- package/habilidades/microservicios/SKILL.md +155 -0
- package/habilidades/microservicios/recursos/patrones-y-ejemplos-completos.md +325 -0
- package/habilidades/mobile-flutter/SKILL.md +199 -0
- package/habilidades/mobile-flutter/recursos/ejemplos-completos.md +319 -0
- package/habilidades/mobile-react-native/SKILL.md +176 -0
- package/habilidades/mobile-react-native/recursos/ejemplos-completos.md +216 -0
- package/habilidades/mongodb-experto/SKILL.md +302 -0
- package/habilidades/monitoring-alertas/SKILL.md +201 -0
- package/habilidades/monitoring-alertas/recursos/instrumentacion-y-alertas.md +301 -0
- package/habilidades/nestjs-experto/SKILL.md +307 -0
- package/habilidades/nestjs-experto/recursos/guards-interceptors.md +339 -0
- package/habilidades/nestjs-experto/recursos/modulos-di.md +287 -0
- package/habilidades/nestjs-experto/recursos/testing-nestjs.md +354 -0
- package/habilidades/nextjs-experto/SKILL.md +335 -0
- package/habilidades/nextjs-patrones/SKILL.md +303 -0
- package/habilidades/nextjs-testing/SKILL.md +331 -0
- package/habilidades/node-experto/.evolved.json +9 -0
- package/habilidades/node-experto/SKILL.md +266 -0
- package/habilidades/node-experto/recursos/patrones-completos.md +283 -0
- package/habilidades/notificaciones-multicanal/SKILL.md +159 -0
- package/habilidades/notificaciones-multicanal/recursos/config-template.json +115 -0
- package/habilidades/notificaciones-multicanal/recursos/configuracion-y-templates.md +303 -0
- package/habilidades/nuevo-proyecto/SKILL.md +204 -0
- package/habilidades/orquestacion-async/SKILL.md +303 -0
- package/habilidades/paid-media-tracking/SKILL.md +269 -0
- package/habilidades/paid-media-tracking/recursos/auditoria-tracking.md +220 -0
- package/habilidades/paid-media-tracking/recursos/google-ads-api.md +215 -0
- package/habilidades/patrones-python/SKILL.md +228 -0
- package/habilidades/patrones-python/evals/evals.json +56 -0
- package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -0
- package/habilidades/patrones-python/recursos/referencia-completa.md +202 -0
- package/habilidades/perfil-usuario/SKILL.md +200 -0
- package/habilidades/perfil-usuario/evals/evals.json +55 -0
- package/habilidades/performance-baseline/SKILL.md +297 -0
- package/habilidades/php-experto/SKILL.md +291 -0
- package/habilidades/php-patrones/SKILL.md +306 -0
- package/habilidades/php-testing/SKILL.md +280 -0
- package/habilidades/planear-fase/SKILL.md +269 -0
- package/habilidades/postgresql-experto/SKILL.md +151 -0
- package/habilidades/postgresql-experto/evals/evals.json +53 -0
- package/habilidades/postgresql-experto/recursos/referencia-completa.md +215 -0
- package/habilidades/prevencion-racionalizacion/SKILL.md +175 -0
- package/habilidades/prevencion-sobreingenieria/SKILL.md +323 -0
- package/habilidades/privacy-memoria/SKILL.md +141 -0
- package/habilidades/privacy-memoria/evals/evals.json +43 -0
- package/habilidades/prompt-engineering/SKILL.md +518 -0
- package/habilidades/prompt-engineering/recursos/patrones-avanzados.md +467 -0
- package/habilidades/rag-arquitectura/SKILL.md +338 -0
- package/habilidades/rails-experto/SKILL.md +237 -0
- package/habilidades/rails-experto/recursos/active-record.md +260 -0
- package/habilidades/rails-experto/recursos/hotwire-turbo.md +293 -0
- package/habilidades/rails-experto/recursos/testing-rspec.md +362 -0
- package/habilidades/react-experto/SKILL.md +209 -0
- package/habilidades/react-experto/evals/evals.json +55 -0
- package/habilidades/react-experto/recursos/patrones-y-ejemplos-completos.md +240 -0
- package/habilidades/react-optimizacion/SKILL.md +174 -0
- package/habilidades/react-optimizacion/recursos/patrones-avanzados.md +138 -0
- package/habilidades/redis-experto/SKILL.md +305 -0
- package/habilidades/release-semver/.evolved.json +9 -0
- package/habilidades/release-semver/SKILL.md +248 -0
- package/habilidades/release-semver/scripts/generar-changelog.sh +238 -0
- package/habilidades/rust-experto/SKILL.md +400 -0
- package/habilidades/rust-patrones/SKILL.md +296 -0
- package/habilidades/rust-testing/SKILL.md +311 -0
- package/habilidades/seguridad-skills-ia/SKILL.md +262 -0
- package/habilidades/sql-optimizacion/SKILL.md +200 -0
- package/habilidades/sql-optimizacion/evals/evals.json +54 -0
- package/habilidades/sql-optimizacion/recursos/patrones-sql-avanzados.md +131 -0
- package/habilidades/sre-patrones/SKILL.md +333 -0
- package/habilidades/sre-patrones/recursos/chaos-engineering.md +241 -0
- package/habilidades/sre-patrones/recursos/oncall-design.md +236 -0
- package/habilidades/stripe-pagos/SKILL.md +550 -0
- package/habilidades/stripe-pagos/recursos/errores-reintentos.md +390 -0
- package/habilidades/stripe-pagos/recursos/stripe-connect.md +290 -0
- package/habilidades/structured-outputs/SKILL.md +343 -0
- package/habilidades/swift-experto/SKILL.md +320 -0
- package/habilidades/swift-experto/recursos/keychain-y-wrappers.md +110 -0
- package/habilidades/swift-patrones/SKILL.md +313 -0
- package/habilidades/swift-patrones/recursos/tca-ejemplo-completo.md +113 -0
- package/habilidades/swift-testing/SKILL.md +254 -0
- package/habilidades/swift-testing/recursos/xcuitest-planes.md +143 -0
- package/habilidades/swl-dashboard/SKILL.md +370 -0
- package/habilidades/swl-markitdown/SKILL.md +285 -0
- package/habilidades/swl-markitdown/evals/evals.json +52 -0
- package/habilidades/swl-revisar-impacto/SKILL.md +233 -0
- package/habilidades/tailwind-experto/SKILL.md +240 -0
- package/habilidades/tailwind-experto/recursos/referencia-completa.md +184 -0
- package/habilidades/tdd-workflow/SKILL.md +293 -0
- package/habilidades/terraform-experto/SKILL.md +321 -0
- package/habilidades/testing-python/SKILL.md +340 -0
- package/habilidades/testing-python/recursos/ejemplos-completos.md +167 -0
- package/habilidades/threat-model-lite/SKILL.md +246 -0
- package/habilidades/tracing-processor/SKILL.md +212 -0
- package/habilidades/tracking-measurement/SKILL.md +239 -0
- package/habilidades/tracking-measurement/recursos/consent-mode.md +231 -0
- package/habilidades/tracking-measurement/recursos/gtm-datalayer.md +216 -0
- package/habilidades/tracking-measurement/recursos/meta-capi.md +262 -0
- package/habilidades/typescript-avanzado/SKILL.md +144 -0
- package/habilidades/typescript-avanzado/evals/evals.json +55 -0
- package/habilidades/typescript-avanzado/recursos/patrones-y-ejemplos-completos.md +298 -0
- package/habilidades/typescript-diagnosticos/SKILL.md +513 -0
- package/habilidades/ux-diseno/SKILL.md +116 -0
- package/habilidades/ux-diseno/evals/evals.json +43 -0
- package/habilidades/ux-diseno/recursos/patrones-ux-referencia.md +214 -0
- package/habilidades/validacion-ci-sistema/SKILL.md +136 -0
- package/habilidades/validacion-ci-sistema/recursos/validadores-completos.md +369 -0
- package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +286 -0
- package/habilidades/verificacion-evidencia/SKILL.md +160 -0
- package/habilidades/verificar-trabajo/SKILL.md +303 -0
- package/habilidades/verificar-trabajo/recursos/plantilla-verificacion.md +60 -0
- package/habilidades/wiki-conocimiento/SKILL.md +276 -0
- package/habilidades/wireframes-flujos/SKILL.md +212 -0
- package/habilidades/wireframes-flujos/recursos/referencia-completa.md +192 -0
- package/habilidades/workflow-claude-code/SKILL.md +260 -0
- package/habilidades/workflow-claude-code/recursos/referencia-completa.md +109 -0
- package/hooks/_run-hook.sh +57 -0
- package/hooks/actualizar-perfil-usuario.js +364 -0
- package/hooks/agente-lifecycle.js +71 -0
- package/hooks/aiisms-detector.js +173 -0
- package/hooks/audit-trail.js +204 -0
- package/hooks/auto-background.js +97 -0
- package/hooks/auto-consolidacion.js +178 -0
- package/hooks/auto-evolucion.js +666 -0
- package/hooks/auto-restaurar-settings.js +360 -0
- package/hooks/calidad-pre-commit.js +929 -0
- package/hooks/calidad-typescript.js +511 -0
- package/hooks/captura-feedback-usuario.js +148 -0
- package/hooks/check-update.js +211 -0
- package/hooks/clasificador-mensajes.js +271 -0
- package/hooks/degradacion-instintos.js +272 -0
- package/hooks/escaneo-secretos.js +389 -0
- package/hooks/extraccion-aprendizajes.js +763 -0
- package/hooks/grafo-contexto.js +129 -0
- package/hooks/graph-update.js +67 -0
- package/hooks/guardrail-modelo.js +247 -0
- package/hooks/inbox-aviso.js +75 -0
- package/hooks/inyeccion-contexto.js +246 -0
- package/hooks/lib/abort-registry.js +214 -0
- package/hooks/lib/agent-backend.js +210 -0
- package/hooks/lib/agent-comms.js +263 -0
- package/hooks/lib/agent-issue-codes.js +284 -0
- package/hooks/lib/agent-matcher.js +189 -0
- package/hooks/lib/async-hook-registry.js +252 -0
- package/hooks/lib/atomic-write.js +130 -0
- package/hooks/lib/auto-consolidator.js +335 -0
- package/hooks/lib/canary-skills.js +187 -0
- package/hooks/lib/consolidation-lock.js +291 -0
- package/hooks/lib/context-builder.js +430 -0
- package/hooks/lib/context-compressor.js +657 -0
- package/hooks/lib/convergence-detector.js +105 -0
- package/hooks/lib/delegation-tracker.js +198 -0
- package/hooks/lib/detectar-package-manager.js +423 -0
- package/hooks/lib/edit-accumulator.js +171 -0
- package/hooks/lib/error-classifier.js +308 -0
- package/hooks/lib/event-bus.js +112 -0
- package/hooks/lib/evolution-tracker.js +442 -0
- package/hooks/lib/execution-state.js +316 -0
- package/hooks/lib/fingerprint-id.js +135 -0
- package/hooks/lib/gateway-notify.js +116 -0
- package/hooks/lib/graph-security.js +75 -0
- package/hooks/lib/guardrail-metrics.js +202 -0
- package/hooks/lib/hook-circuit-breaker.js +206 -0
- package/hooks/lib/loop-detector.js +267 -0
- package/hooks/lib/mcp-health.js +184 -0
- package/hooks/lib/mcp-pool.js +436 -0
- package/hooks/lib/memory-search.js +506 -0
- package/hooks/lib/merkle-audit.js +96 -0
- package/hooks/lib/model-router.js +222 -0
- package/hooks/lib/normalize-error.js +324 -0
- package/hooks/lib/normalize-input.js +65 -0
- package/hooks/lib/nudge-tracker.js +306 -0
- package/hooks/lib/otlp-exporter.js +365 -0
- package/hooks/lib/performance-marks.js +239 -0
- package/hooks/lib/privacy-filter.js +128 -0
- package/hooks/lib/prompt-injection-scanner.js +209 -0
- package/hooks/lib/provenance-tracker.js +183 -0
- package/hooks/lib/rate-limit-tracker.js +253 -0
- package/hooks/lib/reflect-classifier.js +164 -0
- package/hooks/lib/resource-quota.js +122 -0
- package/hooks/lib/retry-jitter.js +165 -0
- package/hooks/lib/risk-engine.js +368 -0
- package/hooks/lib/run-log.js +408 -0
- package/hooks/lib/session-fts.js +379 -0
- package/hooks/lib/session-store.js +293 -0
- package/hooks/lib/singleton-guard.js +159 -0
- package/hooks/lib/skill-auditor.js +588 -0
- package/hooks/lib/sync-status.js +228 -0
- package/hooks/lib/taint-tracker.js +107 -0
- package/hooks/lib/task-service.js +295 -0
- package/hooks/lib/tech-skills-map.js +146 -0
- package/hooks/lib/telegram-cliente.js +159 -0
- package/hooks/lib/telegram-config.js +170 -0
- package/hooks/lib/token-budget.js +156 -0
- package/hooks/lib/token-estimator.js +420 -0
- package/hooks/lib/toon-compressor.js +245 -0
- package/hooks/lib/usage-model.js +183 -0
- package/hooks/lib/variable-resolver.js +230 -0
- package/hooks/linea-estado.js +324 -0
- package/hooks/metricas-evolucion.js +209 -0
- package/hooks/monitor-contexto.js +325 -0
- package/hooks/notificacion-sesion-stop.js +198 -0
- package/hooks/notificacion-telegram-notification.js +4 -0
- package/hooks/notificacion-telegram-subagent.js +4 -0
- package/hooks/notificacion-telegram.js +267 -0
- package/hooks/preservar-estado-pre-compact.js +150 -0
- package/hooks/proteccion-rutas.js +366 -0
- package/hooks/registro-turnos.js +209 -0
- package/hooks/resumen-sesion.js +249 -0
- package/hooks/risk-scoring.js +323 -0
- package/hooks/rotar-audit-auto.js +122 -0
- package/hooks/sugerir-regenerar-inventario.js +170 -0
- package/hooks/telemetria-agentes.js +167 -0
- package/hooks/tracking-costos.js +688 -0
- package/instintos/global.yaml +8 -0
- package/instintos/perfil-usuario.yaml +53 -0
- package/instintos/prompt-appendices.yaml +57 -0
- package/instintos/proyecto.yaml +372 -0
- package/manifiestos/gateway-config.json +77 -0
- package/manifiestos/handoff-context.json +223 -0
- package/manifiestos/hook-profiles.json +44 -0
- package/manifiestos/hooks-config.json +360 -0
- package/manifiestos/modulos.json +1173 -0
- package/manifiestos/perfiles.json +404 -0
- package/package.json +86 -0
- package/plantillas/ESTADO.md +109 -0
- package/plantillas/HOJA-RUTA.md +143 -0
- package/plantillas/PROYECTO.md +122 -0
- package/plantillas/REQUISITOS.md +132 -0
- package/plantillas/auditor-veto-template.md +105 -0
- package/plantillas/github-workflows/README.md +47 -0
- package/plantillas/github-workflows/release-please.yml +44 -0
- package/plantillas/github-workflows/swl-ci.yml +107 -0
- package/plantillas/github-workflows/swl-security.yml +51 -0
- package/plantillas/mcp-mineru.json +13 -0
- package/plantillas/research/ARQUITECTURA.md +220 -0
- package/plantillas/research/FUNCIONALIDADES.md +175 -0
- package/plantillas/research/RESUMEN.md +165 -0
- package/plantillas/research/STACK.md +233 -0
- package/plantillas/research/TRAMPAS.md +299 -0
- package/plantillas/skill-evals-template.json +44 -0
- package/plugin.json +343 -0
- package/reglas/accesibilidad.md +269 -0
- package/reglas/api-diseno.md +400 -0
- package/reglas/arquitectura.md +352 -0
- package/reglas/brevedad-output.md +124 -0
- package/reglas/cloud-infra.md +247 -0
- package/reglas/docs.md +245 -0
- package/reglas/estilo-codigo.md +201 -0
- package/reglas/git-workflow.md +245 -0
- package/reglas/gobernanza.md +271 -0
- package/reglas/harness-claude-code.md +213 -0
- package/reglas/hooks.md +186 -0
- package/reglas/lenguajes/csharp/estilo-codigo.md +231 -0
- package/reglas/lenguajes/csharp/hooks.md +281 -0
- package/reglas/lenguajes/csharp/patrones.md +226 -0
- package/reglas/lenguajes/csharp/seguridad.md +258 -0
- package/reglas/lenguajes/csharp/testing.md +176 -0
- package/reglas/lenguajes/go/estilo-codigo.md +195 -0
- package/reglas/lenguajes/go/hooks.md +249 -0
- package/reglas/lenguajes/go/patrones.md +249 -0
- package/reglas/lenguajes/go/seguridad.md +225 -0
- package/reglas/lenguajes/go/testing.md +272 -0
- package/reglas/lenguajes/java/estilo-codigo.md +217 -0
- package/reglas/lenguajes/java/hooks.md +251 -0
- package/reglas/lenguajes/java/patrones.md +226 -0
- package/reglas/lenguajes/java/seguridad.md +233 -0
- package/reglas/lenguajes/java/testing.md +238 -0
- package/reglas/lenguajes/kotlin/estilo-codigo.md +208 -0
- package/reglas/lenguajes/kotlin/hooks.md +245 -0
- package/reglas/lenguajes/kotlin/patrones.md +201 -0
- package/reglas/lenguajes/kotlin/seguridad.md +202 -0
- package/reglas/lenguajes/kotlin/testing.md +236 -0
- package/reglas/lenguajes/nextjs/estilo-codigo.md +175 -0
- package/reglas/lenguajes/nextjs/hooks.md +186 -0
- package/reglas/lenguajes/nextjs/patrones.md +225 -0
- package/reglas/lenguajes/nextjs/seguridad.md +216 -0
- package/reglas/lenguajes/nextjs/testing.md +193 -0
- package/reglas/lenguajes/php/estilo-codigo.md +228 -0
- package/reglas/lenguajes/php/hooks.md +165 -0
- package/reglas/lenguajes/php/patrones.md +233 -0
- package/reglas/lenguajes/php/seguridad.md +186 -0
- package/reglas/lenguajes/php/testing.md +205 -0
- package/reglas/lenguajes/rust/estilo-codigo.md +207 -0
- package/reglas/lenguajes/rust/hooks.md +240 -0
- package/reglas/lenguajes/rust/patrones.md +250 -0
- package/reglas/lenguajes/rust/seguridad.md +221 -0
- package/reglas/lenguajes/rust/testing.md +194 -0
- package/reglas/lenguajes/swift/estilo-codigo.md +238 -0
- package/reglas/lenguajes/swift/hooks.md +257 -0
- package/reglas/lenguajes/swift/patrones.md +235 -0
- package/reglas/lenguajes/swift/seguridad.md +248 -0
- package/reglas/lenguajes/swift/testing.md +242 -0
- package/reglas/markitdown.md +60 -0
- package/reglas/memoria-consolidada.md +209 -0
- package/reglas/patrones.md +225 -0
- package/reglas/performance.md +195 -0
- package/reglas/pruebas.md +159 -0
- package/reglas/seguridad-agentes.md +351 -0
- package/reglas/seguridad.md +151 -0
- package/reglas/skills-estandar.md +373 -0
- package/reglas/testing.md +193 -0
- package/schemas/agent-contract.json +176 -0
- package/schemas/agent-frontmatter.schema.json +149 -0
- package/schemas/agent-message.schema.json +53 -0
- package/schemas/agent-output-implementacion.schema.json +85 -0
- package/schemas/agent-output-planificacion.schema.json +113 -0
- package/schemas/agent-output-review.schema.json +78 -0
- package/schemas/diary-entry.schema.json +80 -0
- package/schemas/hook-profiles.schema.json +39 -0
- package/schemas/hooks-config.schema.json +74 -0
- package/schemas/instinct.schema.json +115 -0
- package/schemas/modulos.schema.json +29 -0
- package/schemas/perfiles.schema.json +28 -0
- package/schemas/plugin.schema.json +64 -0
- package/schemas/skill-evals.schema.json +95 -0
- package/schemas/skill-frontmatter.schema.json +170 -0
- package/scripts/actualizar.js +145 -0
- package/scripts/audit-skills.sh +78 -0
- package/scripts/auditar-agentes-gaps.js +149 -0
- package/scripts/auditar-cobertura-frameworks.js +241 -0
- package/scripts/auditar-skills-gaps.js +206 -0
- package/scripts/bootstrap-instintos.js +259 -0
- package/scripts/check-update.js +109 -0
- package/scripts/comandos/agents.js +105 -0
- package/scripts/comandos/info.js +108 -0
- package/scripts/comandos/install-asistido.js +186 -0
- package/scripts/comandos/skills.js +211 -0
- package/scripts/configurar-branch-protection.js +418 -0
- package/scripts/daemon-swl.py +388 -0
- package/scripts/desinstalar.js +130 -0
- package/scripts/doctor.js +559 -0
- package/scripts/field-report.js +199 -0
- package/scripts/generar-inventario.js +317 -0
- package/scripts/inbox-tmux-inject.js +161 -0
- package/scripts/inferir-herramientas-permitidas.js +586 -0
- package/scripts/inicializar.js +133 -0
- package/scripts/instalador.js +1031 -0
- package/scripts/instalar-git-hook.js +122 -0
- package/scripts/lib/agp-frontmatter.js +222 -0
- package/scripts/lib/append-con-marcadores.js +199 -0
- package/scripts/lib/artefactos-python.js +43 -0
- package/scripts/lib/audit-query.js +221 -0
- package/scripts/lib/autostart-linux.js +347 -0
- package/scripts/lib/autostart-macos.js +360 -0
- package/scripts/lib/autostart-windows.js +307 -0
- package/scripts/lib/budget-enforcer.js +252 -0
- package/scripts/lib/claude-sessions.js +285 -0
- package/scripts/lib/configurar-ci.js +380 -0
- package/scripts/lib/console-span-exporter.js +92 -0
- package/scripts/lib/contadores-inventario.js +217 -0
- package/scripts/lib/dashboard-widgets.js +290 -0
- package/scripts/lib/detectar-runtime.js +279 -0
- package/scripts/lib/detectar-stack.js +187 -0
- package/scripts/lib/diary-entry.js +234 -0
- package/scripts/lib/drift-detector.js +545 -0
- package/scripts/lib/estado.js +124 -0
- package/scripts/lib/gestor-componentes.js +243 -0
- package/scripts/lib/gitignore-manifest.js +305 -0
- package/scripts/lib/graph-analyze.py +556 -0
- package/scripts/lib/graph-builder.py +485 -0
- package/scripts/lib/graph-cluster.py +259 -0
- package/scripts/lib/health-row.js +168 -0
- package/scripts/lib/hooks-settings.js +789 -0
- package/scripts/lib/manifiestos.js +138 -0
- package/scripts/lib/mc-client.js +137 -0
- package/scripts/lib/notificaciones-telegram.js +1107 -0
- package/scripts/lib/npm-version.js +261 -0
- package/scripts/lib/paquetes-conocidos.js +50 -0
- package/scripts/lib/preservar-usuario.js +586 -0
- package/scripts/lib/prompt-builder.js +264 -0
- package/scripts/lib/resolver-externo.js +332 -0
- package/scripts/lib/schedule-parser.js +305 -0
- package/scripts/lib/scoring-instintos.js +240 -0
- package/scripts/lib/seguridad.js +160 -0
- package/scripts/lib/selector-interactivo.js +152 -0
- package/scripts/lib/semantic-search.js +242 -0
- package/scripts/lib/skill-discovery.js +234 -0
- package/scripts/lib/skill-metrics.js +246 -0
- package/scripts/lib/skill-normalizer.js +112 -0
- package/scripts/lib/skills-hub.js +340 -0
- package/scripts/lib/span-schema.js +134 -0
- package/scripts/lib/tool-cost-analyzer.js +255 -0
- package/scripts/lib/tracing-processor-interface.js +286 -0
- package/scripts/lib/transformadores/base.js +80 -0
- package/scripts/lib/transformadores/claude.js +124 -0
- package/scripts/lib/transformadores/codex.js +115 -0
- package/scripts/lib/transformadores/copilot.js +106 -0
- package/scripts/lib/transformadores/gemini.js +74 -0
- package/scripts/lib/transformadores/index.js +35 -0
- package/scripts/lib/transformadores/opencode.js +75 -0
- package/scripts/lib/ui.js +259 -0
- package/scripts/limpiar-artefactos-python.js +131 -0
- package/scripts/mcp-orchestrator.py +386 -0
- package/scripts/mcp-pool-manager.py +352 -0
- package/scripts/mcp-telemetry.py +378 -0
- package/scripts/poblar-evolvable.js +226 -0
- package/scripts/publicar.js +287 -0
- package/scripts/reflect-skills.js +403 -0
- package/scripts/rotar-audit-logs.js +185 -0
- package/scripts/run-skill-evals.js +242 -0
- package/scripts/smoke-test.js +374 -0
- package/scripts/token-analysis.py +471 -0
- package/scripts/validar-manifest.js +195 -0
- package/scripts/validar-memoria.js +321 -0
- package/scripts/validar-tests-aislamiento.js +184 -0
- package/scripts/validar-tokens-test.js +208 -0
- package/scripts/validar.js +147 -0
- package/scripts/validate-markdown.py +339 -0
- package/scripts/validate-skills.py +385 -0
- package/scripts/vendor/claude-usage/README.md +116 -0
- package/scripts/vendor/claude-usage/cli.py +334 -0
- package/scripts/vendor/claude-usage/dashboard.py +795 -0
- package/scripts/vendor/claude-usage/scanner.py +467 -0
- package/scripts/vendor/markitdown/cli.py +194 -0
- package/scripts/verificar-evolucion.js +289 -0
- package/scripts/verificar-release.js +494 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Regla: Testing — PHP / Laravel
|
|
2
|
+
|
|
3
|
+
Los tests en PHP con Laravel cubren dos dimensiones: lógica de negocio aislada
|
|
4
|
+
(unit tests) y comportamiento HTTP end-to-end (feature tests). Esta regla define
|
|
5
|
+
cuándo usar cada tipo, cómo estructurarlos y qué herramientas son válidas.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Frameworks de testing
|
|
10
|
+
|
|
11
|
+
- **PHPUnit**: framework base, ya incluido en Laravel. Usar para proyectos existentes.
|
|
12
|
+
- **Pest**: alternativa moderna con sintaxis más concisa. Usar para proyectos nuevos
|
|
13
|
+
o cuando el equipo lo adopte conscientemente.
|
|
14
|
+
- No mezclar PHPUnit y Pest en el mismo proyecto sin consenso del equipo.
|
|
15
|
+
- **Mockery**: para mocks y stubs. Integrado con ambos frameworks.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Cobertura mínima: 80%
|
|
20
|
+
|
|
21
|
+
- Ejecutar con reporte de cobertura:
|
|
22
|
+
```bash
|
|
23
|
+
php artisan test --coverage --min=80
|
|
24
|
+
```
|
|
25
|
+
- CI falla si la cobertura cae por debajo del 80%.
|
|
26
|
+
- La cobertura se mide sobre código de negocio: `app/Services/`, `app/Repositories/`,
|
|
27
|
+
`app/Models/`. No sobre controllers ni providers.
|
|
28
|
+
- Cobertura del 100% con tests triviales no es el objetivo. 80% con tests
|
|
29
|
+
que prueban comportamiento real vale más.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Feature tests para endpoints HTTP
|
|
34
|
+
|
|
35
|
+
Los feature tests verifican el comportamiento completo del endpoint, incluyendo
|
|
36
|
+
middleware, validación, respuesta y efectos en la BD:
|
|
37
|
+
|
|
38
|
+
```php
|
|
39
|
+
class EmitirFacturaTest extends TestCase
|
|
40
|
+
{
|
|
41
|
+
use RefreshDatabase;
|
|
42
|
+
|
|
43
|
+
public function test_usuario_autorizado_puede_emitir_factura(): void
|
|
44
|
+
{
|
|
45
|
+
// Arrange
|
|
46
|
+
$empresa = Empresa::factory()->create();
|
|
47
|
+
$usuario = User::factory()->para($empresa)->conRol('admin')->create();
|
|
48
|
+
$cliente = Cliente::factory()->para($empresa)->create();
|
|
49
|
+
|
|
50
|
+
// Act
|
|
51
|
+
$respuesta = $this->actingAs($usuario)
|
|
52
|
+
->postJson('/api/v1/facturas', [
|
|
53
|
+
'cliente_id' => $cliente->id,
|
|
54
|
+
'items' => [
|
|
55
|
+
['sku' => 'PROD-01', 'qty' => 2, 'precio' => 100.00],
|
|
56
|
+
],
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
// Assert
|
|
60
|
+
$respuesta->assertCreated()
|
|
61
|
+
->assertJsonPath('data.estatus', 'emitida')
|
|
62
|
+
->assertJsonPath('data.cliente.id', $cliente->id);
|
|
63
|
+
|
|
64
|
+
$this->assertDatabaseHas('facturas', [
|
|
65
|
+
'empresa_id' => $empresa->id,
|
|
66
|
+
'estatus' => 'emitida',
|
|
67
|
+
]);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public function test_usuario_sin_rol_admin_recibe_403(): void
|
|
71
|
+
{
|
|
72
|
+
$usuario = User::factory()->conRol('visor').create();
|
|
73
|
+
|
|
74
|
+
$this->actingAs($usuario)
|
|
75
|
+
->postJson('/api/v1/facturas', [])
|
|
76
|
+
->assertForbidden();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Unit tests para lógica de negocio
|
|
84
|
+
|
|
85
|
+
Los unit tests prueban services y clases de dominio en aislamiento, mockeando
|
|
86
|
+
todas las dependencias externas:
|
|
87
|
+
|
|
88
|
+
```php
|
|
89
|
+
class CalculadoraImpuestoTest extends TestCase
|
|
90
|
+
{
|
|
91
|
+
public function test_calcula_iva_sobre_precio_base(): void
|
|
92
|
+
{
|
|
93
|
+
// Arrange
|
|
94
|
+
$calculadora = new CalculadoraImpuesto(tasaIva: 0.16);
|
|
95
|
+
|
|
96
|
+
// Act
|
|
97
|
+
$resultado = $calculadora->calcularIva(precio: 100.0);
|
|
98
|
+
|
|
99
|
+
// Assert
|
|
100
|
+
$this->assertEqualsWithDelta(16.0, $resultado, delta: 0.001);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public function test_lanza_excepcion_con_precio_negativo(): void
|
|
104
|
+
{
|
|
105
|
+
$calculadora = new CalculadoraImpuesto(tasaIva: 0.16);
|
|
106
|
+
|
|
107
|
+
$this->expectException(\InvalidArgumentException::class);
|
|
108
|
+
$this->expectExceptionMessage('El precio no puede ser negativo');
|
|
109
|
+
|
|
110
|
+
$calculadora->calcularIva(precio: -1.0);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Factories para datos de prueba
|
|
118
|
+
|
|
119
|
+
- NUNCA crear registros de BD con `new Model()` ni arrays hardcodeados en tests.
|
|
120
|
+
- Usar Laravel Model Factories. Definir estados para variaciones comunes:
|
|
121
|
+
|
|
122
|
+
```php
|
|
123
|
+
class FacturaFactory extends Factory
|
|
124
|
+
{
|
|
125
|
+
public function definition(): array
|
|
126
|
+
{
|
|
127
|
+
return [
|
|
128
|
+
'folio' => 'FAC-' . $this->faker->unique()->numerify('#####'),
|
|
129
|
+
'estatus' => EstatusFactura::Borrador,
|
|
130
|
+
'total' => $this->faker->randomFloat(2, 100, 10000),
|
|
131
|
+
'fecha_emision' => $this->faker->dateTimeBetween('-1 year', 'now'),
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public function emitida(): static
|
|
136
|
+
{
|
|
137
|
+
return $this->state(['estatus' => EstatusFactura::Emitida]);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public function cancelada(): static
|
|
141
|
+
{
|
|
142
|
+
return $this->state(['estatus' => EstatusFactura::Cancelada]);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Database testing: RefreshDatabase vs DatabaseTransactions
|
|
150
|
+
|
|
151
|
+
| Trait | Cuándo usar | Costo |
|
|
152
|
+
|-------|------------|-------|
|
|
153
|
+
| `RefreshDatabase` | Tests que modifican el schema o necesitan estado limpio garantizado | Alto — hace migrate:fresh por clase |
|
|
154
|
+
| `DatabaseTransactions` | Tests CRUD simples sin cambios de schema | Bajo — rollback al final de cada test |
|
|
155
|
+
|
|
156
|
+
- Preferir `DatabaseTransactions` para tests de feature rápidos.
|
|
157
|
+
- Usar `RefreshDatabase` solo cuando el test necesita un estado absolutamente limpio.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Mocks con Mockery
|
|
162
|
+
|
|
163
|
+
```php
|
|
164
|
+
public function test_emitir_factura_envia_email_al_cliente(): void
|
|
165
|
+
{
|
|
166
|
+
// Arrange
|
|
167
|
+
$mailer = Mockery::mock(MailerInterface::class);
|
|
168
|
+
$mailer->shouldReceive('enviarFactura')
|
|
169
|
+
->once()
|
|
170
|
+
->with(Mockery::type(Factura::class));
|
|
171
|
+
|
|
172
|
+
$service = new FacturaService(
|
|
173
|
+
facturas: $this->app->make(FacturaRepositoryInterface::class),
|
|
174
|
+
mailer: $mailer,
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
$factura = Factura::factory()->create();
|
|
178
|
+
|
|
179
|
+
// Act
|
|
180
|
+
$service->emitir($factura->id);
|
|
181
|
+
|
|
182
|
+
// Assert — verificado por Mockery::shouldReceive()->once()
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Patrón Arrange-Act-Assert (AAA)
|
|
189
|
+
|
|
190
|
+
- Cada test tiene exactamente tres bloques separados con comentario.
|
|
191
|
+
- Una sola afirmación conceptual por test. Múltiples `assert*` sobre el mismo
|
|
192
|
+
resultado están bien; verificar comportamientos distintos en el mismo test no.
|
|
193
|
+
- Nombre del test: `test_[escenario]_[resultado_esperado]`.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Checklist de testing antes de merge
|
|
198
|
+
|
|
199
|
+
- [ ] `php artisan test --coverage --min=80` pasa
|
|
200
|
+
- [ ] Feature test para cada endpoint nuevo
|
|
201
|
+
- [ ] Unit test para cada método público de Service nuevo
|
|
202
|
+
- [ ] Factories usadas para todos los registros de BD en tests
|
|
203
|
+
- [ ] Sin `sleep()` ni dependencias de tiempo real (usar `Carbon::setTestNow()`)
|
|
204
|
+
- [ ] Patron AAA con comentarios en cada test
|
|
205
|
+
- [ ] Test de regresión para cada bug corregido
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Regla: Estilo de Código — Rust
|
|
2
|
+
|
|
3
|
+
Aplica a todo código Rust del proyecto. El compilador de Rust ya impone muchas
|
|
4
|
+
restricciones; estas reglas cubren las decisiones de estilo y legibilidad que
|
|
5
|
+
el compilador no puede forzar. El objetivo es código que sea seguro, claro y
|
|
6
|
+
que cualquier miembro del equipo pueda mantener con confianza.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Formateo con rustfmt (obligatorio)
|
|
11
|
+
|
|
12
|
+
- `rustfmt` es el formateador oficial y su uso es obligatorio. No se aceptan
|
|
13
|
+
PRs con código sin formatear.
|
|
14
|
+
- El archivo `rustfmt.toml` en la raíz del proyecto define la configuración.
|
|
15
|
+
Si no existe, usar los valores por defecto de rustfmt.
|
|
16
|
+
- Ejecutar antes de cada commit: `cargo fmt --check` para verificar sin modificar.
|
|
17
|
+
- NUNCA editar manualmente el indentado o el espaciado — dejar que rustfmt decida.
|
|
18
|
+
- CI debe fallar si `cargo fmt --check` produce diferencias.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Clippy como linter (obligatorio)
|
|
23
|
+
|
|
24
|
+
- Clippy detecta errores idiomáticos que rustfmt no cubre.
|
|
25
|
+
- Ejecutar con: `cargo clippy -- -D warnings`
|
|
26
|
+
El flag `-D warnings` convierte todo warning en error — CI falla si hay alguno.
|
|
27
|
+
- Cuando un lint de Clippy es incorrecto para el caso específico, suprimir
|
|
28
|
+
con `#[allow(clippy::nombre_del_lint)]` en el sitio exacto, con comentario
|
|
29
|
+
explicando por qué:
|
|
30
|
+
```rust
|
|
31
|
+
#[allow(clippy::too_many_arguments)] // Esta función es el punto de entrada del CLI y requiere todos estos parámetros
|
|
32
|
+
pub fn ejecutar(...) { ... }
|
|
33
|
+
```
|
|
34
|
+
- NUNCA `#![allow(clippy::all)]` a nivel de crate — suprime lints válidos.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Convenciones de nombres
|
|
39
|
+
|
|
40
|
+
| Elemento | Convención | Ejemplo |
|
|
41
|
+
|----------|-----------|---------|
|
|
42
|
+
| Funciones y métodos | `snake_case` | `calcular_total()` |
|
|
43
|
+
| Variables y parámetros | `snake_case` | `precio_unitario` |
|
|
44
|
+
| Constantes y statics | `SCREAMING_SNAKE_CASE` | `MAX_REINTENTOS` |
|
|
45
|
+
| Tipos, traits, enums | `PascalCase` | `FacturaError`, `Pagable` |
|
|
46
|
+
| Variantes de enum | `PascalCase` | `EstadoPedido::Enviado` |
|
|
47
|
+
| Módulos y archivos | `snake_case` | `factura_service.rs` |
|
|
48
|
+
| Lifetimes | `'a`, `'b` o nombres cortos descriptivos | `'entrada`, `'cache` |
|
|
49
|
+
|
|
50
|
+
- NUNCA abreviar nombres de tipos. `UsrMngr` — mal. `UserManager` — bien.
|
|
51
|
+
- Prefijo `is_` / `has_` para métodos que retornan `bool`:
|
|
52
|
+
`is_active()`, `has_items()`, `can_retry()`.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Ownership y borrowing: reglas de cuándo usar qué
|
|
57
|
+
|
|
58
|
+
| Situación | Usar | Razón |
|
|
59
|
+
|-----------|------|-------|
|
|
60
|
+
| Leer datos sin modificar | `&T` | Préstamo inmutable, sin costo de copia |
|
|
61
|
+
| Modificar datos en el lugar | `&mut T` | Préstamo mutable |
|
|
62
|
+
| Tomar posesión para almacenar | `T` (move) | El caller ya no necesita el valor |
|
|
63
|
+
| Compartir entre hilos | `Arc<T>` | Reference counting atómico |
|
|
64
|
+
| Mutación compartida entre hilos | `Arc<Mutex<T>>` | Exclusión mutua |
|
|
65
|
+
|
|
66
|
+
**Parámetros de función**:
|
|
67
|
+
- Preferir `&str` sobre `&String` — acepta tanto `&str` como `&String`.
|
|
68
|
+
- Preferir `&[T]` sobre `&Vec<T>` — acepta cualquier slice.
|
|
69
|
+
- Preferir `&Path` sobre `&PathBuf`.
|
|
70
|
+
- Usar `impl Trait` para aceptar cualquier implementador del trait:
|
|
71
|
+
|
|
72
|
+
```rust
|
|
73
|
+
// MAL — restringe a String específicamente
|
|
74
|
+
fn saludar(nombre: &String) -> String { ... }
|
|
75
|
+
|
|
76
|
+
// BIEN — acepta &str, &String, Cow<str>, etc.
|
|
77
|
+
fn saludar(nombre: &str) -> String { ... }
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Retornos**:
|
|
81
|
+
- Retornar `String` (owned) cuando el caller necesita poseer el valor.
|
|
82
|
+
- Retornar `&str` solo cuando el lifetime está atado al receiver (`&self`).
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Organización de módulos
|
|
87
|
+
|
|
88
|
+
- Organizar módulos por **dominio**, no por tipo de artefacto.
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
// MAL — organizado por tipo
|
|
92
|
+
src/
|
|
93
|
+
models/
|
|
94
|
+
services/
|
|
95
|
+
handlers/
|
|
96
|
+
|
|
97
|
+
// BIEN — organizado por dominio
|
|
98
|
+
src/
|
|
99
|
+
facturacion/
|
|
100
|
+
mod.rs
|
|
101
|
+
factura.rs
|
|
102
|
+
calculo.rs
|
|
103
|
+
usuario/
|
|
104
|
+
mod.rs
|
|
105
|
+
autenticacion.rs
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
- Cada módulo tiene su `mod.rs` que re-exporta solo lo público necesario.
|
|
109
|
+
- Módulos de utilidades genéricas van en `src/comun/` o `src/infra/`.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Visibilidad por defecto: privada
|
|
114
|
+
|
|
115
|
+
- Todo es privado por defecto en Rust. `pub` solo cuando el símbolo es
|
|
116
|
+
parte de la interfaz pública intencional del módulo.
|
|
117
|
+
- Escala de visibilidad (usar la más restrictiva posible):
|
|
118
|
+
1. Privado (sin modificador) — solo dentro del módulo
|
|
119
|
+
2. `pub(super)` — visible en el módulo padre
|
|
120
|
+
3. `pub(crate)` — visible en todo el crate
|
|
121
|
+
4. `pub` — visible fuera del crate (API pública)
|
|
122
|
+
- Los campos de struct son privados por defecto. Exponer solo con métodos
|
|
123
|
+
o con `pub` cuando sea realmente necesario.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## No unwrap() en código de producción
|
|
128
|
+
|
|
129
|
+
- `unwrap()` y `expect()` panicanean en runtime. Prohibidos en `src/` fuera de tests.
|
|
130
|
+
- Usar el operador `?` para propagar errores.
|
|
131
|
+
- Usar combinators de `Option` para manejar la ausencia de valor:
|
|
132
|
+
|
|
133
|
+
```rust
|
|
134
|
+
// MAL — panics si el valor es None
|
|
135
|
+
let config = env::var("DATABASE_URL").unwrap();
|
|
136
|
+
|
|
137
|
+
// BIEN — propaga el error con contexto
|
|
138
|
+
let config = env::var("DATABASE_URL")
|
|
139
|
+
.map_err(|_| ConfigError::MissingEnvVar("DATABASE_URL"))?;
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
- `expect()` solo está permitido en código de inicio de la aplicación
|
|
143
|
+
(main, configuración inicial) donde un panic es aceptable, y con mensaje descriptivo:
|
|
144
|
+
`config.load().expect("No se pudo cargar configuración inicial")`.
|
|
145
|
+
- En tests: `unwrap()` y `expect()` son aceptables.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Iteradores sobre loops indexados
|
|
150
|
+
|
|
151
|
+
```rust
|
|
152
|
+
// MAL — loop indexado, verboso y propenso a off-by-one
|
|
153
|
+
for i in 0..facturas.len() {
|
|
154
|
+
procesar(&facturas[i]);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// BIEN — iterador idiomático
|
|
158
|
+
for factura in &facturas {
|
|
159
|
+
procesar(factura);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// BIEN — con transformación
|
|
163
|
+
let totales: Vec<f64> = facturas.iter().map(|f| f.total()).collect();
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
- Prefer `iter()` sobre índices directos en la mayoría de los casos.
|
|
167
|
+
- `iter_mut()` para modificación in-place. `into_iter()` para consumir.
|
|
168
|
+
- Cadenas de iteradores (`map`, `filter`, `flat_map`, `fold`) sobre loops
|
|
169
|
+
cuando la operación es una transformación de datos.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Lifetimes explícitos: solo cuando el compilador no infiere
|
|
174
|
+
|
|
175
|
+
- No agregar lifetimes donde el compilador puede inferirlos (elision rules).
|
|
176
|
+
- Lifetimes explícitos en structs que contienen referencias:
|
|
177
|
+
|
|
178
|
+
```rust
|
|
179
|
+
// NECESARIO — el struct contiene una referencia
|
|
180
|
+
struct Analizador<'a> {
|
|
181
|
+
datos: &'a [u8],
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// INNECESARIO — el compilador infiere correctamente
|
|
185
|
+
fn primera_linea(texto: &str) -> &str { ... }
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Longitud máxima de función: 50 líneas
|
|
191
|
+
|
|
192
|
+
- Las funciones no deben exceder 50 líneas de código efectivo.
|
|
193
|
+
- Funciones largas se dividen en funciones privadas con nombres descriptivos.
|
|
194
|
+
- Los métodos de `impl` siguen la misma regla.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Checklist de estilo antes de hacer commit
|
|
199
|
+
|
|
200
|
+
- [ ] `cargo fmt --check` pasa sin diferencias
|
|
201
|
+
- [ ] `cargo clippy -- -D warnings` pasa sin warnings
|
|
202
|
+
- [ ] Sin `unwrap()` ni `expect()` en `src/` fuera de tests y main
|
|
203
|
+
- [ ] Parámetros de función usan `&str` / `&[T]` en lugar de `&String` / `&Vec<T>`
|
|
204
|
+
- [ ] Sin loops indexados donde un iterador funciona igual
|
|
205
|
+
- [ ] Visibilidad mínima necesaria en todos los símbolos
|
|
206
|
+
- [ ] Módulos organizados por dominio, no por tipo de artefacto
|
|
207
|
+
- [ ] Funciones <= 50 líneas
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# Regla: Hooks de Calidad — Rust
|
|
2
|
+
|
|
3
|
+
Checks automáticos que se ejecutan en distintos puntos del ciclo de desarrollo
|
|
4
|
+
para detectar problemas antes de que lleguen a revisión de código o a producción.
|
|
5
|
+
Ningún check es opcional — todos bloquean el flujo si detectan un problema.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## cargo fmt --check antes de commit
|
|
10
|
+
|
|
11
|
+
**Pre-commit hook** — bloquea el commit si el código no está formateado:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
#!/usr/bin/env bash
|
|
15
|
+
# .git/hooks/pre-commit o configurado via pre-commit framework
|
|
16
|
+
|
|
17
|
+
set -e
|
|
18
|
+
|
|
19
|
+
echo "Verificando formato con rustfmt..."
|
|
20
|
+
cargo fmt --check
|
|
21
|
+
|
|
22
|
+
if [ $? -ne 0 ]; then
|
|
23
|
+
echo "ERROR: El código no está formateado."
|
|
24
|
+
echo "Ejecutar: cargo fmt"
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Con el framework `pre-commit` (recomendado para equipos):
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
# .pre-commit-config.yaml
|
|
33
|
+
repos:
|
|
34
|
+
- repo: local
|
|
35
|
+
hooks:
|
|
36
|
+
- id: cargo-fmt
|
|
37
|
+
name: cargo fmt
|
|
38
|
+
language: system
|
|
39
|
+
entry: cargo fmt --check
|
|
40
|
+
pass_filenames: false
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- Si el check falla: ejecutar `cargo fmt` (sin `--check`) y hacer el commit de nuevo.
|
|
44
|
+
- NUNCA commitear con `--no-verify` para saltarse el formato.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## cargo clippy -- -D warnings antes de commit
|
|
49
|
+
|
|
50
|
+
**Pre-commit hook** — bloquea el commit si hay warnings de Clippy:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
echo "Ejecutando Clippy..."
|
|
54
|
+
cargo clippy --all-targets --all-features -- -D warnings
|
|
55
|
+
|
|
56
|
+
if [ $? -ne 0 ]; then
|
|
57
|
+
echo "ERROR: Clippy encontró warnings."
|
|
58
|
+
echo "Corregir los warnings antes de hacer commit."
|
|
59
|
+
exit 1
|
|
60
|
+
fi
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- `--all-targets` incluye tests, benchmarks y ejemplos — no solo el código de producción.
|
|
64
|
+
- `--all-features` activa todos los feature flags para detectar problemas en cualquier configuración.
|
|
65
|
+
- Si un lint específico de Clippy es un falso positivo para el caso en cuestión,
|
|
66
|
+
suprimir con `#[allow(clippy::lint_name)]` en el sitio exacto, con comentario.
|
|
67
|
+
NUNCA suprimir a nivel de crate.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## cargo test antes de merge
|
|
72
|
+
|
|
73
|
+
**CI — bloquea el merge si algún test falla**:
|
|
74
|
+
|
|
75
|
+
```yaml
|
|
76
|
+
# .github/workflows/ci.yml
|
|
77
|
+
jobs:
|
|
78
|
+
test:
|
|
79
|
+
runs-on: ubuntu-latest
|
|
80
|
+
steps:
|
|
81
|
+
- uses: actions/checkout@v4
|
|
82
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
83
|
+
- uses: Swatinem/rust-cache@v2
|
|
84
|
+
|
|
85
|
+
- name: Ejecutar tests
|
|
86
|
+
run: cargo test --all-targets --all-features
|
|
87
|
+
|
|
88
|
+
- name: Cobertura de código
|
|
89
|
+
run: |
|
|
90
|
+
cargo install cargo-llvm-cov --locked
|
|
91
|
+
cargo llvm-cov --all-features --fail-under-lines 80
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- `cargo test` se ejecuta en CI en cada PR — no solo antes de merge.
|
|
95
|
+
- Los tests deben pasar en el runner de CI, no solo en la máquina local.
|
|
96
|
+
- La cobertura se verifica como parte del mismo job de tests.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## cargo-audit en CI semanal
|
|
101
|
+
|
|
102
|
+
**Job separado — ejecuta semanalmente y en PRs que modifican Cargo.lock**:
|
|
103
|
+
|
|
104
|
+
```yaml
|
|
105
|
+
# .github/workflows/audit.yml
|
|
106
|
+
name: Security Audit
|
|
107
|
+
|
|
108
|
+
on:
|
|
109
|
+
schedule:
|
|
110
|
+
- cron: '0 6 * * 1' # Lunes a las 6am UTC
|
|
111
|
+
push:
|
|
112
|
+
paths:
|
|
113
|
+
- 'Cargo.lock'
|
|
114
|
+
- 'Cargo.toml'
|
|
115
|
+
|
|
116
|
+
jobs:
|
|
117
|
+
audit:
|
|
118
|
+
runs-on: ubuntu-latest
|
|
119
|
+
steps:
|
|
120
|
+
- uses: actions/checkout@v4
|
|
121
|
+
- uses: rustsec/audit-check@v1
|
|
122
|
+
with:
|
|
123
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
- El job de auditoría falla si encuentra vulnerabilidades HIGH o CRITICAL.
|
|
127
|
+
- Las alertas de `cargo audit` se notifican al canal de seguridad del equipo.
|
|
128
|
+
- Vulnerabilidades MEDIUM generan warning — deben resolverse en <2 semanas.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Detección de println! en código no-test
|
|
133
|
+
|
|
134
|
+
**Custom Clippy lint via CI** — detecta prints de debug que no deben llegar a producción:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# En el job de CI, después de los tests
|
|
138
|
+
echo "Verificando que no hay println! en código de producción..."
|
|
139
|
+
|
|
140
|
+
# Buscar println! en src/ pero no en mod tests ni en main.rs
|
|
141
|
+
if grep -rn "println!" src/ --include="*.rs" | grep -v "#\[cfg(test)\]" | grep -v "fn main"; then
|
|
142
|
+
echo "ERROR: println! encontrado en código de producción."
|
|
143
|
+
echo "Usar tracing::info! o tracing::debug! en su lugar."
|
|
144
|
+
exit 1
|
|
145
|
+
fi
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Alternativamente, via Clippy con configuración en `clippy.toml`:
|
|
149
|
+
|
|
150
|
+
```toml
|
|
151
|
+
# clippy.toml
|
|
152
|
+
# Prohibir macros de debugging en código de producción
|
|
153
|
+
disallowed-macros = [
|
|
154
|
+
{ path = "std::println", reason = "Usar tracing::info! en código de producción" },
|
|
155
|
+
{ path = "std::eprintln", reason = "Usar tracing::error! en código de producción" },
|
|
156
|
+
{ path = "std::dbg", reason = "Macro de debugging — eliminar antes de merge" },
|
|
157
|
+
]
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
- `println!` y `eprintln!` están permitidos solo en:
|
|
161
|
+
- `src/main.rs` para output esperado de CLIs
|
|
162
|
+
- `#[cfg(test)] mod tests`
|
|
163
|
+
- Ejemplos en `examples/`
|
|
164
|
+
- En el resto del código: usar `tracing::info!`, `tracing::debug!`, `tracing::error!`.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Detección de unwrap() y expect() en src/
|
|
169
|
+
|
|
170
|
+
**Parte del hook de pre-commit** — detecta panics potenciales en código de producción:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
echo "Verificando ausencia de unwrap()/expect() en código de producción..."
|
|
174
|
+
|
|
175
|
+
# Buscar en src/ excluyendo módulos de test
|
|
176
|
+
if grep -rn "\.unwrap()\|\.expect(" src/ --include="*.rs" \
|
|
177
|
+
| grep -v "#\[cfg(test)\]" \
|
|
178
|
+
| grep -v "// ALLOW-UNWRAP:"; then
|
|
179
|
+
echo "ERROR: unwrap()/expect() encontrado en código de producción."
|
|
180
|
+
echo "Usar el operador ? o manejo explícito de errores."
|
|
181
|
+
echo "Si el unwrap() está justificado, agregar comentario: // ALLOW-UNWRAP: razón"
|
|
182
|
+
exit 1
|
|
183
|
+
fi
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
- `unwrap()` y `expect()` están permitidos en:
|
|
187
|
+
- `#[cfg(test)] mod tests`
|
|
188
|
+
- `src/main.rs` para inicialización de la aplicación (con `expect()` descriptivo)
|
|
189
|
+
- Código marcado con `// ALLOW-UNWRAP: <razón explícita>`
|
|
190
|
+
- Cuando se necesita `expect()` fuera de tests: el mensaje debe explicar por qué
|
|
191
|
+
el `None`/`Err` es imposible en ese punto.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Configuración completa recomendada
|
|
196
|
+
|
|
197
|
+
```yaml
|
|
198
|
+
# .pre-commit-config.yaml — instalar con: pre-commit install
|
|
199
|
+
repos:
|
|
200
|
+
- repo: local
|
|
201
|
+
hooks:
|
|
202
|
+
- id: cargo-fmt
|
|
203
|
+
name: Formato (rustfmt)
|
|
204
|
+
language: system
|
|
205
|
+
entry: cargo fmt --check
|
|
206
|
+
pass_filenames: false
|
|
207
|
+
|
|
208
|
+
- id: cargo-clippy
|
|
209
|
+
name: Linter (clippy)
|
|
210
|
+
language: system
|
|
211
|
+
entry: cargo clippy --all-targets -- -D warnings
|
|
212
|
+
pass_filenames: false
|
|
213
|
+
|
|
214
|
+
- id: no-println
|
|
215
|
+
name: Sin println! en producción
|
|
216
|
+
language: pygrep
|
|
217
|
+
entry: '\bprintln!\('
|
|
218
|
+
files: '^src/(?!main\.rs).*\.rs$'
|
|
219
|
+
exclude: '#\[cfg\(test\)\]'
|
|
220
|
+
|
|
221
|
+
- id: no-unwrap
|
|
222
|
+
name: Sin unwrap() en producción
|
|
223
|
+
language: pygrep
|
|
224
|
+
entry: '\.unwrap\(\)'
|
|
225
|
+
files: '^src/.*\.rs$'
|
|
226
|
+
exclude: '(#\[cfg\(test\)\]|ALLOW-UNWRAP)'
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Checklist de hooks antes de integrar al proyecto
|
|
232
|
+
|
|
233
|
+
- [ ] `pre-commit install` ejecutado en el repositorio del proyecto
|
|
234
|
+
- [ ] `cargo fmt --check` en el hook de pre-commit
|
|
235
|
+
- [ ] `cargo clippy -- -D warnings` en el hook de pre-commit
|
|
236
|
+
- [ ] `cargo test` en el pipeline de CI (cada PR)
|
|
237
|
+
- [ ] `cargo audit` en job semanal de CI
|
|
238
|
+
- [ ] Detección de `println!` en `src/` fuera de tests y main
|
|
239
|
+
- [ ] Detección de `unwrap()` en `src/` fuera de tests
|
|
240
|
+
- [ ] Cobertura mínima del 80% verificada en CI
|