@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,258 @@
|
|
|
1
|
+
# Regla: Seguridad — C# / .NET
|
|
2
|
+
|
|
3
|
+
ASP.NET Core tiene un buen punto de partida en seguridad, pero muchas de sus
|
|
4
|
+
protecciones deben habilitarse explícitamente. Esta regla cubre las configuraciones
|
|
5
|
+
obligatorias para que el punto de partida seguro sea la norma, no la excepción.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## OWASP Top 10 para .NET
|
|
10
|
+
|
|
11
|
+
Antes de cerrar cualquier ticket que toque autenticación, autorización o datos,
|
|
12
|
+
verificar que no se introduce ninguna vulnerabilidad del OWASP Top 10:
|
|
13
|
+
|
|
14
|
+
- **Inyección (A03)**: EF Core usa parámetros por defecto — nunca interpolar variables
|
|
15
|
+
en `FromSqlRaw()` ni `ExecuteSqlRaw()`.
|
|
16
|
+
- **Control de acceso roto (A01)**: `[Authorize]` en todos los controllers y endpoints
|
|
17
|
+
por defecto; `[AllowAnonymous]` explícito solo en los que lo requieren.
|
|
18
|
+
- **Fallos criptográficos (A02)**: HTTPS obligatorio, datos sensibles cifrados en reposo
|
|
19
|
+
con `IDataProtectionProvider`, no con implementaciones propias.
|
|
20
|
+
- **Componentes vulnerables (A06)**: `dotnet list package --vulnerable` en CI.
|
|
21
|
+
- **Fallos de logging y monitoreo (A09)**: No loggear datos sensibles (passwords, tokens, PII).
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Entity Framework Core: queries parametrizadas por defecto
|
|
26
|
+
|
|
27
|
+
EF Core parametriza automáticamente. Los errores ocurren cuando se sale de ese camino:
|
|
28
|
+
|
|
29
|
+
```csharp
|
|
30
|
+
// MAL — interpolación directa en SQL crudo, susceptible a inyección
|
|
31
|
+
var email = userInput; // potencialmente malicioso
|
|
32
|
+
var facturas = await _db.Facturas
|
|
33
|
+
.FromSqlRaw($"SELECT * FROM facturas WHERE email = '{email}'")
|
|
34
|
+
.ToListAsync();
|
|
35
|
+
|
|
36
|
+
// MAL — aunque se use parámetro, la interpolación de C# no es SQL parameter
|
|
37
|
+
var facturas = await _db.Database
|
|
38
|
+
.ExecuteSqlRawAsync($"DELETE FROM facturas WHERE id = {id}");
|
|
39
|
+
|
|
40
|
+
// BIEN — FromSqlInterpolated usa parámetros seguros automáticamente
|
|
41
|
+
var facturas = await _db.Facturas
|
|
42
|
+
.FromSqlInterpolated($"SELECT * FROM facturas WHERE email = {email}")
|
|
43
|
+
.ToListAsync();
|
|
44
|
+
|
|
45
|
+
// BIEN — parámetro explícito con FromSqlRaw
|
|
46
|
+
var facturas = await _db.Facturas
|
|
47
|
+
.FromSqlRaw("SELECT * FROM facturas WHERE email = {0}", email)
|
|
48
|
+
.ToListAsync();
|
|
49
|
+
|
|
50
|
+
// MEJOR — LINQ con EF Core (parámetros automáticos siempre)
|
|
51
|
+
var facturas = await _db.Facturas
|
|
52
|
+
.Where(f => f.ClienteEmail == email)
|
|
53
|
+
.ToListAsync();
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- Regla simple: si hay interpolación de strings en SQL → es un bug de seguridad.
|
|
57
|
+
- `FromSqlInterpolated` es la excepción segura cuando se necesita SQL crudo.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## ASP.NET Core: [Authorize] por defecto
|
|
62
|
+
|
|
63
|
+
```csharp
|
|
64
|
+
// Program.cs — política de autorización por defecto
|
|
65
|
+
builder.Services.AddAuthorization(opts =>
|
|
66
|
+
{
|
|
67
|
+
// Todo endpoint requiere autenticación por defecto
|
|
68
|
+
opts.FallbackPolicy = new AuthorizationPolicyBuilder()
|
|
69
|
+
.RequireAuthenticatedUser()
|
|
70
|
+
.Build();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Los endpoints públicos deben marcarse EXPLÍCITAMENTE
|
|
74
|
+
[AllowAnonymous]
|
|
75
|
+
app.MapGet("/health", () => Results.Ok("healthy"));
|
|
76
|
+
|
|
77
|
+
// Los endpoints con roles específicos
|
|
78
|
+
[Authorize(Roles = "Admin,Facturador")]
|
|
79
|
+
app.MapPost("/facturas", async (IMediator mediator) => { ... });
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- El modelo por defecto es: todo requiere autenticación, lo público se declara explícitamente.
|
|
83
|
+
- NUNCA depender de que los endpoints "no están en producción" para no protegerlos.
|
|
84
|
+
- `[Authorize(Policy = "nombre")]` para autorización basada en policies (más flexible que roles).
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Anti-forgery tokens en formularios
|
|
89
|
+
|
|
90
|
+
```csharp
|
|
91
|
+
// En páginas Razor o controladores MVC
|
|
92
|
+
// Program.cs — habilitado por defecto en Razor Pages
|
|
93
|
+
builder.Services.AddRazorPages();
|
|
94
|
+
// o con configuración explícita
|
|
95
|
+
builder.Services.AddControllersWithViews(opts =>
|
|
96
|
+
{
|
|
97
|
+
opts.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```html
|
|
102
|
+
<!-- En el formulario Razor -->
|
|
103
|
+
<form method="post">
|
|
104
|
+
@Html.AntiForgeryToken()
|
|
105
|
+
<!-- campos del formulario -->
|
|
106
|
+
</form>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
- APIs que usan JWT en el header `Authorization` son inmunes a CSRF por diseño —
|
|
110
|
+
documentar explícitamente en el controller que no se necesita CSRF protection y por qué:
|
|
111
|
+
```csharp
|
|
112
|
+
[ApiController] // implica [ValidateAntiForgeryToken] deshabilitado para JSON APIs con JWT
|
|
113
|
+
[Route("api/[controller]")]
|
|
114
|
+
// CSRF no aplica: esta API usa JWT en Authorization header, no cookies
|
|
115
|
+
public class FacturasController : ControllerBase { ... }
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## User secrets para desarrollo local
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Inicializar user secrets en el proyecto
|
|
124
|
+
dotnet user-secrets init
|
|
125
|
+
|
|
126
|
+
# Agregar secreto para desarrollo
|
|
127
|
+
dotnet user-secrets set "ConnectionStrings:Default" "Server=localhost;Database=dev;..."
|
|
128
|
+
dotnet user-secrets set "Jwt:SecretKey" "clave-solo-para-desarrollo"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
- User secrets nunca se versionan en git — se almacenan en `%APPDATA%/Microsoft/UserSecrets/`.
|
|
132
|
+
- Solo para ambiente de desarrollo. En staging y producción: Azure Key Vault o AWS Secrets Manager.
|
|
133
|
+
- El archivo `appsettings.Development.json` NUNCA contiene secretos reales — solo configuración
|
|
134
|
+
no sensible de desarrollo.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Azure Key Vault / AWS Secrets Manager en producción
|
|
139
|
+
|
|
140
|
+
```csharp
|
|
141
|
+
// Program.cs — integración con Azure Key Vault
|
|
142
|
+
if (builder.Environment.IsProduction())
|
|
143
|
+
{
|
|
144
|
+
var keyVaultUri = new Uri(builder.Configuration["KeyVaultUri"]!);
|
|
145
|
+
builder.Configuration.AddAzureKeyVault(
|
|
146
|
+
keyVaultUri,
|
|
147
|
+
new DefaultAzureCredential()); // usa Managed Identity en Azure
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
- `DefaultAzureCredential` usa Managed Identity automáticamente en Azure — sin API keys.
|
|
152
|
+
- Las variables de entorno y configuración de producción NUNCA se almacenan en el repositorio.
|
|
153
|
+
- Los secretos de Key Vault se cargan en el `IConfiguration` estándar — el código no cambia.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## No usar BinaryFormatter
|
|
158
|
+
|
|
159
|
+
`BinaryFormatter` fue deprecado y tiene vulnerabilidades conocidas de ejecución
|
|
160
|
+
remota de código (RCE) via deserialización maliciosa.
|
|
161
|
+
|
|
162
|
+
```csharp
|
|
163
|
+
// PROHIBIDO — BinaryFormatter puede ejecutar código arbitrario
|
|
164
|
+
var formatter = new BinaryFormatter();
|
|
165
|
+
objeto = (MiTipo)formatter.Deserialize(stream); // CVE-2022-34716 y otros
|
|
166
|
+
|
|
167
|
+
// BIEN — alternativas seguras
|
|
168
|
+
// Para datos internos estructurados:
|
|
169
|
+
var json = JsonSerializer.Serialize(objeto);
|
|
170
|
+
var restaurado = JsonSerializer.Deserialize<MiTipo>(json);
|
|
171
|
+
|
|
172
|
+
// Para datos binarios de alto rendimiento:
|
|
173
|
+
// MessagePack, protobuf-net (con tipos explícitos registrados)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
- El compilador emite SYSLIB0011 cuando se usa `BinaryFormatter` — tratar como error.
|
|
177
|
+
- Si se necesita serialización binaria: usar `System.Text.Json`, `MessagePack` o `ProtoBuf`.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Content Security Policy headers
|
|
182
|
+
|
|
183
|
+
```csharp
|
|
184
|
+
// Program.cs — agregar headers de seguridad en todas las respuestas
|
|
185
|
+
app.Use(async (context, next) =>
|
|
186
|
+
{
|
|
187
|
+
context.Response.Headers.Append("X-Content-Type-Options", "nosniff");
|
|
188
|
+
context.Response.Headers.Append("X-Frame-Options", "DENY");
|
|
189
|
+
context.Response.Headers.Append("X-XSS-Protection", "1; mode=block");
|
|
190
|
+
context.Response.Headers.Append(
|
|
191
|
+
"Content-Security-Policy",
|
|
192
|
+
"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'");
|
|
193
|
+
context.Response.Headers.Append(
|
|
194
|
+
"Strict-Transport-Security",
|
|
195
|
+
"max-age=31536000; includeSubDomains");
|
|
196
|
+
await next();
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
- Usar el paquete `NWebsec.AspNetCore.Middleware` para configuración más completa de CSP.
|
|
201
|
+
- Ajustar la CSP según los recursos externos que la aplicación necesita cargar.
|
|
202
|
+
- Probar la CSP con https://csp-evaluator.withgoogle.com/.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Rate limiting con el middleware nativo de .NET 7+
|
|
207
|
+
|
|
208
|
+
```csharp
|
|
209
|
+
// Program.cs
|
|
210
|
+
builder.Services.AddRateLimiter(opts =>
|
|
211
|
+
{
|
|
212
|
+
// Límite global por IP
|
|
213
|
+
opts.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(
|
|
214
|
+
context => RateLimitPartition.GetFixedWindowLimiter(
|
|
215
|
+
context.Connection.RemoteIpAddress?.ToString() ?? "unknown",
|
|
216
|
+
_ => new FixedWindowRateLimiterOptions
|
|
217
|
+
{
|
|
218
|
+
PermitLimit = 100,
|
|
219
|
+
Window = TimeSpan.FromMinutes(1)
|
|
220
|
+
}));
|
|
221
|
+
|
|
222
|
+
// Límite estricto para endpoints de autenticación
|
|
223
|
+
opts.AddPolicy("autenticacion", context =>
|
|
224
|
+
RateLimitPartition.GetFixedWindowLimiter(
|
|
225
|
+
context.Connection.RemoteIpAddress?.ToString() ?? "unknown",
|
|
226
|
+
_ => new FixedWindowRateLimiterOptions
|
|
227
|
+
{
|
|
228
|
+
PermitLimit = 5,
|
|
229
|
+
Window = TimeSpan.FromMinutes(1)
|
|
230
|
+
}));
|
|
231
|
+
|
|
232
|
+
opts.OnRejected = async (context, ct) =>
|
|
233
|
+
{
|
|
234
|
+
context.HttpContext.Response.StatusCode = 429;
|
|
235
|
+
await context.HttpContext.Response.WriteAsync(
|
|
236
|
+
"Demasiadas solicitudes. Intenta de nuevo en un minuto.", ct);
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
app.UseRateLimiter();
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
- .NET 7+ tiene rate limiting nativo — no requiere paquetes externos para casos comunes.
|
|
244
|
+
- Aplicar políticas más estrictas en endpoints de autenticación (`/login`, `/register`).
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Checklist de seguridad antes de hacer merge
|
|
249
|
+
|
|
250
|
+
- [ ] Sin interpolación de strings en `FromSqlRaw` o `ExecuteSqlRaw`
|
|
251
|
+
- [ ] Todos los endpoints protegidos con `[Authorize]` o `[AllowAnonymous]` explícito
|
|
252
|
+
- [ ] Sin secretos en `appsettings*.json`, `user-secrets` solo en desarrollo
|
|
253
|
+
- [ ] Azure Key Vault o equivalente configurado para producción
|
|
254
|
+
- [ ] `BinaryFormatter` no utilizado en ningún lugar del código nuevo
|
|
255
|
+
- [ ] Headers de seguridad configurados (`X-Content-Type-Options`, `X-Frame-Options`, CSP)
|
|
256
|
+
- [ ] Rate limiting en endpoints de autenticación
|
|
257
|
+
- [ ] `dotnet list package --vulnerable` pasa sin vulnerabilidades HIGH o CRITICAL
|
|
258
|
+
- [ ] Logs sin datos sensibles (passwords, tokens, datos personales)
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Regla: Pruebas — C# / .NET
|
|
2
|
+
|
|
3
|
+
Las pruebas en .NET tienen un ecosistema maduro. Estas reglas establecen el
|
|
4
|
+
stack estándar del proyecto y cómo usarlo para tests deterministas, legibles
|
|
5
|
+
y mantenibles.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## xUnit como framework principal
|
|
10
|
+
|
|
11
|
+
- xUnit es el framework estándar. No usar NUnit ni MSTest en proyectos nuevos.
|
|
12
|
+
- Estructura:
|
|
13
|
+
```
|
|
14
|
+
tests/
|
|
15
|
+
├── MiProyecto.UnitTests/
|
|
16
|
+
└── MiProyecto.IntegrationTests/
|
|
17
|
+
```
|
|
18
|
+
- Un proyecto de tests por capa — no mezclar unitarios e integración.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## NSubstitute para mocks
|
|
23
|
+
|
|
24
|
+
NSubstitute para todos los mocks. No Moq (historial de cambios de licencia):
|
|
25
|
+
|
|
26
|
+
```csharp
|
|
27
|
+
// Crear y configurar mock
|
|
28
|
+
var repo = Substitute.For<IFacturaRepository>();
|
|
29
|
+
repo.ObtenerPorIdAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>())
|
|
30
|
+
.Returns(new Factura(/* ... */));
|
|
31
|
+
|
|
32
|
+
// Verificar que fue llamado exactamente una vez
|
|
33
|
+
await repo.Received(1).AgregarAsync(
|
|
34
|
+
Arg.Is<Factura>(f => f.Total == 1500m),
|
|
35
|
+
Arg.Any<CancellationToken>());
|
|
36
|
+
|
|
37
|
+
// Simular error
|
|
38
|
+
repo.ObtenerPorIdAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>())
|
|
39
|
+
.ThrowsAsync(new TimeoutException());
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- Mockear solo interfaces y clases abstractas — no clases concretas del dominio.
|
|
43
|
+
- NUNCA mockear la clase bajo prueba — señal de acoplamiento excesivo.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## FluentAssertions para assertions legibles
|
|
48
|
+
|
|
49
|
+
```csharp
|
|
50
|
+
// MAL — difícil de leer en mensajes de fallo
|
|
51
|
+
Assert.Equal(1500m, factura.Total);
|
|
52
|
+
Assert.NotNull(factura.Cliente);
|
|
53
|
+
|
|
54
|
+
// BIEN — mensajes de error descriptivos automáticos
|
|
55
|
+
factura.Total.Should().Be(1500m);
|
|
56
|
+
factura.Cliente.Should().NotBeNull();
|
|
57
|
+
facturas.Should().HaveCount(3)
|
|
58
|
+
.And.ContainSingle(f => f.Estatus == EstadoFactura.Pagada);
|
|
59
|
+
|
|
60
|
+
// Para objetos complejos — ignora campos no relevantes
|
|
61
|
+
resultado.Should().BeEquivalentTo(esperado,
|
|
62
|
+
opts => opts.Excluding(f => f.FechaCreacion));
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## TestContainers para integración
|
|
68
|
+
|
|
69
|
+
```csharp
|
|
70
|
+
public class DatabaseFixture : IAsyncLifetime
|
|
71
|
+
{
|
|
72
|
+
private readonly PostgreSqlContainer _postgres = new PostgreSqlBuilder()
|
|
73
|
+
.WithDatabase("testdb").WithUsername("test").WithPassword("test")
|
|
74
|
+
.Build();
|
|
75
|
+
|
|
76
|
+
public string ConnectionString => _postgres.GetConnectionString();
|
|
77
|
+
public async Task InitializeAsync() => await _postgres.StartAsync();
|
|
78
|
+
public async Task DisposeAsync() => await _postgres.DisposeAsync();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
[Collection("Database")]
|
|
82
|
+
public class FacturaRepositoryTests : IClassFixture<DatabaseFixture>
|
|
83
|
+
{
|
|
84
|
+
public FacturaRepositoryTests(DatabaseFixture db) { /* usar db.ConnectionString */ }
|
|
85
|
+
|
|
86
|
+
[Fact]
|
|
87
|
+
public async Task Should_PersistFactura_When_Added() { ... }
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
- TestContainers para tests de repositorio contra PostgreSQL real.
|
|
92
|
+
- `IClassFixture<T>` para compartir el contenedor entre tests del mismo archivo.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## WebApplicationFactory para tests de API
|
|
97
|
+
|
|
98
|
+
```csharp
|
|
99
|
+
public class FacturasApiTests : IClassFixture<WebApplicationFactory<Program>>
|
|
100
|
+
{
|
|
101
|
+
private readonly HttpClient _client;
|
|
102
|
+
|
|
103
|
+
public FacturasApiTests(WebApplicationFactory<Program> factory)
|
|
104
|
+
{
|
|
105
|
+
_client = factory.WithWebHostBuilder(builder =>
|
|
106
|
+
builder.ConfigureServices(services =>
|
|
107
|
+
{
|
|
108
|
+
services.RemoveAll<AppDbContext>();
|
|
109
|
+
services.AddDbContext<AppDbContext>(opts =>
|
|
110
|
+
opts.UseInMemoryDatabase("TestDb"));
|
|
111
|
+
}))
|
|
112
|
+
.CreateClient();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
[Fact]
|
|
116
|
+
public async Task Should_Return200_When_FacturaExists()
|
|
117
|
+
{
|
|
118
|
+
var response = await _client.GetAsync($"/facturas/{Guid.NewGuid()}");
|
|
119
|
+
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
- Reemplazar dependencias de infraestructura (BD, servicios externos) con dobles.
|
|
125
|
+
- BD in-memory para tests de API (velocidad), TestContainers para tests de repositorio (fidelidad).
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Cobertura mínima 80% con coverlet
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
dotnet test --collect:"XPlat Code Coverage"
|
|
133
|
+
reportgenerator -reports:"**/coverage.cobertura.xml" -targetdir:./coverage-report
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- CI falla si cobertura cae por debajo del 80% en proyectos de lógica de negocio.
|
|
137
|
+
- Proyectos de infraestructura y configuración: umbral mínimo del 60%.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Patrón Arrange-Act-Assert
|
|
142
|
+
|
|
143
|
+
```csharp
|
|
144
|
+
[Fact]
|
|
145
|
+
public async Task Should_ReturnError_When_ClienteNoExiste()
|
|
146
|
+
{
|
|
147
|
+
// Arrange
|
|
148
|
+
_clienteRepo.ExisteAsync(Arg.Any<string>(), Arg.Any<CancellationToken>())
|
|
149
|
+
.Returns(false);
|
|
150
|
+
|
|
151
|
+
// Act
|
|
152
|
+
var resultado = await _handler.Handle(
|
|
153
|
+
new CrearFacturaCommand("test@test.com", 1500m),
|
|
154
|
+
CancellationToken.None);
|
|
155
|
+
|
|
156
|
+
// Assert
|
|
157
|
+
resultado.IsFailed.Should().BeTrue();
|
|
158
|
+
resultado.Errors.Should().ContainSingle(e => e.Message.Contains("Cliente"));
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
- Nombre del test: `Should_[resultado]_When_[condicion]`.
|
|
163
|
+
- Tests parametrizados con `[Theory]` + `[InlineData]` — no duplicar el cuerpo del test.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Checklist de pruebas antes de hacer merge
|
|
168
|
+
|
|
169
|
+
- [ ] xUnit + NSubstitute + FluentAssertions en todos los tests nuevos
|
|
170
|
+
- [ ] Tests nuevos para todo código nuevo de negocio
|
|
171
|
+
- [ ] Test de regresión escrito antes del fix para todo bug
|
|
172
|
+
- [ ] Cobertura >= 80% verificada con coverlet en CI
|
|
173
|
+
- [ ] Sin `Thread.Sleep` en tests — usar `TimeProvider` mockeado
|
|
174
|
+
- [ ] Tests de integración con TestContainers o WebApplicationFactory
|
|
175
|
+
- [ ] Patrón Arrange-Act-Assert con separación visual clara
|
|
176
|
+
- [ ] Naming: `Should_[resultado]_When_[condicion]`
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Regla: Estilo de Código Go
|
|
2
|
+
|
|
3
|
+
Go tiene una sola forma correcta de formatear código: `gofmt`. Esta regla
|
|
4
|
+
complementa el estilo mecánico con las convenciones idiomáticas de Go que
|
|
5
|
+
no puede verificar una herramienta automática. Seguirlas hace que el código
|
|
6
|
+
sea reconocible para cualquier desarrollador Go, no solo para el equipo.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## gofmt es la ley — sin alternativa ni discusión
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# Obligatorio antes de cada commit
|
|
14
|
+
gofmt -w .
|
|
15
|
+
|
|
16
|
+
# O con goimports (superset de gofmt que también ordena imports)
|
|
17
|
+
goimports -w .
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Un PR que no pasa `gofmt -l .` (que lista archivos mal formateados) no pasa CI.
|
|
21
|
+
No se debate el formato — gofmt es la autoridad. Si el equipo no está de acuerdo
|
|
22
|
+
con alguna decisión de gofmt, el equipo está equivocado.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## goimports para organización de imports
|
|
27
|
+
|
|
28
|
+
`goimports` aplica gofmt y además organiza imports en grupos separados por línea en blanco:
|
|
29
|
+
|
|
30
|
+
```go
|
|
31
|
+
import (
|
|
32
|
+
// Paquetes de la standard library
|
|
33
|
+
"context"
|
|
34
|
+
"fmt"
|
|
35
|
+
"time"
|
|
36
|
+
|
|
37
|
+
// Dependencias externas
|
|
38
|
+
"github.com/google/uuid"
|
|
39
|
+
"go.uber.org/zap"
|
|
40
|
+
|
|
41
|
+
// Paquetes internos del proyecto
|
|
42
|
+
"github.com/miempresa/miapp/internal/domain"
|
|
43
|
+
"github.com/miempresa/miapp/internal/repository"
|
|
44
|
+
)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Nombres: cortos en scope corto, descriptivos en exportados
|
|
50
|
+
|
|
51
|
+
Effective Go es la referencia. Las convenciones de naming en Go son distintas a otros lenguajes.
|
|
52
|
+
|
|
53
|
+
```go
|
|
54
|
+
// BIEN — nombres cortos para variables de scope corto (loops, funciones pequeñas)
|
|
55
|
+
for i, v := range facturas {
|
|
56
|
+
total += v.Total
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if err := repo.Guardar(ctx, factura); err != nil {
|
|
60
|
+
return fmt.Errorf("guardar factura: %w", err)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// BIEN — nombres descriptivos para exportados y variables de scope amplio
|
|
64
|
+
type FacturaRepository interface {
|
|
65
|
+
BuscarPorID(ctx context.Context, id uuid.UUID) (*Factura, error)
|
|
66
|
+
ListarPorCliente(ctx context.Context, clienteID uuid.UUID) ([]*Factura, error)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// MAL — nombre largo para variable de loop (innecesariamente verbose)
|
|
70
|
+
for indiceDeIteracion, facturaActual := range facturas { ... }
|
|
71
|
+
|
|
72
|
+
// MAL — nombre críptico para exportado
|
|
73
|
+
func Proc(c context.Context, f *Fct) (*Res, error) { ... }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Reglas específicas:
|
|
77
|
+
- Acrónimos exportados en MAYÚSCULAS: `URL`, `HTTP`, `ID`, no `Url`, `Http`, `Id`.
|
|
78
|
+
- Interfaces de un solo método: nombre del método + `-er`: `Reader`, `Writer`, `Stringer`.
|
|
79
|
+
- No repetir el nombre del paquete: `factura.Factura` → `factura.Nueva()` retorna `*Factura`.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## "Accept interfaces, return structs"
|
|
84
|
+
|
|
85
|
+
Las funciones aceptan interfaces (para desacoplamiento y testabilidad) y retornan
|
|
86
|
+
tipos concretos (para claridad del llamador).
|
|
87
|
+
|
|
88
|
+
```go
|
|
89
|
+
// MAL — retorna interface: el llamador no sabe qué métodos tiene disponibles
|
|
90
|
+
func NuevoServicio(repo FacturaRepository) FacturaServiceInterface { ... }
|
|
91
|
+
|
|
92
|
+
// BIEN — retorna struct: el llamador sabe exactamente qué recibe
|
|
93
|
+
func NuevoServicio(repo FacturaRepository) *FacturaService { ... }
|
|
94
|
+
|
|
95
|
+
// BIEN — acepta interface: se puede inyectar cualquier implementación
|
|
96
|
+
type FacturaService struct {
|
|
97
|
+
repo FacturaRepository // interface, no *FacturaRepositoryPostgres
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Errores se manejan SIEMPRE — nunca `_ = f()`
|
|
104
|
+
|
|
105
|
+
En Go, ignorar un error es una decisión explícita que requiere justificación.
|
|
106
|
+
`_ = f()` sin comentario es código incorrecto.
|
|
107
|
+
|
|
108
|
+
```go
|
|
109
|
+
// MAL — error ignorado silenciosamente
|
|
110
|
+
archivo, _ := os.Open(ruta)
|
|
111
|
+
defer archivo.Close()
|
|
112
|
+
|
|
113
|
+
// MAL — error ignorado con blank identifier sin justificación
|
|
114
|
+
_ = repositorio.Guardar(ctx, factura)
|
|
115
|
+
|
|
116
|
+
// BIEN — error manejado
|
|
117
|
+
archivo, err := os.Open(ruta)
|
|
118
|
+
if err != nil {
|
|
119
|
+
return fmt.Errorf("abrir archivo %s: %w", ruta, err)
|
|
120
|
+
}
|
|
121
|
+
defer archivo.Close()
|
|
122
|
+
|
|
123
|
+
// BIEN — si realmente se ignora, documentar POR QUÉ
|
|
124
|
+
_ = cache.Invalidar(key) // Error no crítico: la caché se reconstruye automáticamente
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Múltiples return values: (resultado, error)
|
|
130
|
+
|
|
131
|
+
El patrón estándar de Go para operaciones que pueden fallar. Nunca usar
|
|
132
|
+
excepciones ni panics para flujo de control normal.
|
|
133
|
+
|
|
134
|
+
```go
|
|
135
|
+
// Siempre: (valor, error) — el error va último
|
|
136
|
+
func BuscarFactura(ctx context.Context, id uuid.UUID) (*Factura, error) {
|
|
137
|
+
factura, err := repo.FindByID(ctx, id)
|
|
138
|
+
if err != nil {
|
|
139
|
+
return nil, fmt.Errorf("buscar factura %s: %w", id, err)
|
|
140
|
+
}
|
|
141
|
+
if factura == nil {
|
|
142
|
+
return nil, ErrFacturaNoEncontrada
|
|
143
|
+
}
|
|
144
|
+
return factura, nil
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Consumo idiomático
|
|
148
|
+
factura, err := BuscarFactura(ctx, id)
|
|
149
|
+
if err != nil {
|
|
150
|
+
// manejar error
|
|
151
|
+
}
|
|
152
|
+
// usar factura — garantizado no-nil aquí
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Comentarios en funciones exportadas obligatorios
|
|
158
|
+
|
|
159
|
+
Toda función, tipo o constante exportada DEBE tener comentario en formato godoc.
|
|
160
|
+
El comentario empieza con el nombre del símbolo.
|
|
161
|
+
|
|
162
|
+
```go
|
|
163
|
+
// MAL — sin comentario
|
|
164
|
+
func (s *FacturaService) Crear(ctx context.Context, req CrearRequest) (*Factura, error) { ... }
|
|
165
|
+
|
|
166
|
+
// MAL — comentario que no sigue convención godoc
|
|
167
|
+
// Esta función crea una factura
|
|
168
|
+
func (s *FacturaService) Crear(...) { ... }
|
|
169
|
+
|
|
170
|
+
// BIEN — empieza con el nombre del símbolo
|
|
171
|
+
// Crear genera una nueva factura a partir de la solicitud dada.
|
|
172
|
+
// Retorna ErrClienteInactivo si el cliente no está activo en el momento de la creación.
|
|
173
|
+
func (s *FacturaService) Crear(ctx context.Context, req CrearRequest) (*Factura, error) { ... }
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Límites de tamaño
|
|
179
|
+
|
|
180
|
+
- Máximo **50 líneas** por función (sin contar comentarios y líneas en blanco).
|
|
181
|
+
- Archivos grandes son señal de baja cohesión. Si un archivo supera 300 líneas,
|
|
182
|
+
evaluar si el paquete tiene una sola responsabilidad.
|
|
183
|
+
- Paquetes con muchos archivos de <50 líneas son paquetes superficiales — considerar consolidar.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Checklist de estilo Go antes de abrir PR
|
|
188
|
+
|
|
189
|
+
- [ ] `gofmt -l .` retorna vacío (ningún archivo mal formateado)
|
|
190
|
+
- [ ] `goimports -l .` retorna vacío (imports organizados)
|
|
191
|
+
- [ ] Funciones y tipos exportados tienen comentarios godoc
|
|
192
|
+
- [ ] Sin `_ = f()` sin justificación en comentario
|
|
193
|
+
- [ ] Acrónimos exportados en MAYÚSCULAS (URL, ID, HTTP)
|
|
194
|
+
- [ ] Funciones <= 50 líneas
|
|
195
|
+
- [ ] Interfaces aceptadas como parámetros, structs retornados
|