@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.
Files changed (702) hide show
  1. package/CLAUDE.md +238 -0
  2. package/README.md +560 -0
  3. package/_userland/agentes/.gitkeep +0 -0
  4. package/_userland/habilidades/.gitkeep +0 -0
  5. package/agentes/.evolved.json +9 -0
  6. package/agentes/accesibilidad-wcag-swl.md +692 -0
  7. package/agentes/arquitecto-swl.md +238 -0
  8. package/agentes/auto-evolucion-swl.md +854 -0
  9. package/agentes/backend-api-swl.md +470 -0
  10. package/agentes/backend-csharp-swl.md +418 -0
  11. package/agentes/backend-go-swl.md +388 -0
  12. package/agentes/backend-java-swl.md +279 -0
  13. package/agentes/backend-node-swl.md +477 -0
  14. package/agentes/backend-python-swl.md +608 -0
  15. package/agentes/backend-rust-swl.md +362 -0
  16. package/agentes/backend-workers-swl.md +480 -0
  17. package/agentes/cloud-infra-swl.md +485 -0
  18. package/agentes/consolidador-swl.md +539 -0
  19. package/agentes/datos-swl.md +584 -0
  20. package/agentes/depurador-swl.md +349 -0
  21. package/agentes/devops-ci-swl.md +374 -0
  22. package/agentes/disenador-ui-swl.md +558 -0
  23. package/agentes/documentador-swl.md +343 -0
  24. package/agentes/evals/arquitecto-swl.evals.json +56 -0
  25. package/agentes/evals/auto-evolucion-swl.evals.json +68 -0
  26. package/agentes/evals/implementador-swl.evals.json +56 -0
  27. package/agentes/evals/orquestador-swl.evals.json +60 -0
  28. package/agentes/evals/perfilador-usuario-swl.evals.json +60 -0
  29. package/agentes/evals/red-team-swl.evals.json +59 -0
  30. package/agentes/evals/revisor-codigo-swl.evals.json +59 -0
  31. package/agentes/frontend-angular-swl.md +627 -0
  32. package/agentes/frontend-css-swl.md +720 -0
  33. package/agentes/frontend-react-swl.md +696 -0
  34. package/agentes/frontend-swl.md +500 -0
  35. package/agentes/frontend-tailwind-swl.md +830 -0
  36. package/agentes/implementador-swl.md +328 -0
  37. package/agentes/investigador-swl.md +430 -0
  38. package/agentes/investigador-ux-swl.md +500 -0
  39. package/agentes/llm-apps-swl.md +276 -0
  40. package/agentes/migrador-swl.md +417 -0
  41. package/agentes/mobile-android-swl.md +509 -0
  42. package/agentes/mobile-cross-swl.md +539 -0
  43. package/agentes/mobile-ios-swl.md +500 -0
  44. package/agentes/mobile-testing-swl.md +300 -0
  45. package/agentes/notificador-swl.md +916 -0
  46. package/agentes/observabilidad-swl.md +436 -0
  47. package/agentes/orquestador-swl.md +884 -0
  48. package/agentes/pagos-swl.md +283 -0
  49. package/agentes/perfilador-usuario-swl.md +306 -0
  50. package/agentes/planificador-swl.md +402 -0
  51. package/agentes/producto-prd-swl.md +587 -0
  52. package/agentes/red-team-swl.md +216 -0
  53. package/agentes/release-manager-swl.md +568 -0
  54. package/agentes/rendimiento-swl.md +714 -0
  55. package/agentes/resolutor-build-swl.md +243 -0
  56. package/agentes/revisor-angular-swl.md +276 -0
  57. package/agentes/revisor-codigo-swl.md +348 -0
  58. package/agentes/revisor-csharp-swl.md +262 -0
  59. package/agentes/revisor-go-swl.md +257 -0
  60. package/agentes/revisor-java-swl.md +255 -0
  61. package/agentes/revisor-kotlin-swl.md +271 -0
  62. package/agentes/revisor-nextjs-swl.md +279 -0
  63. package/agentes/revisor-php-swl.md +269 -0
  64. package/agentes/revisor-react-swl.md +276 -0
  65. package/agentes/revisor-rust-swl.md +344 -0
  66. package/agentes/revisor-seguridad-swl.md +390 -0
  67. package/agentes/revisor-swift-swl.md +266 -0
  68. package/agentes/revisor-typescript-swl.md +344 -0
  69. package/agentes/sre-swl.md +265 -0
  70. package/agentes/tdd-qa-swl.md +354 -0
  71. package/agentes/ux-disenador-swl.md +501 -0
  72. package/bin/lib/bot-comandos.js +1030 -0
  73. package/bin/lib/bot-discovery.js +182 -0
  74. package/bin/lib/bot-git.js +142 -0
  75. package/bin/swl-ses.js +325 -0
  76. package/bin/swl-telegram-bot.js +442 -0
  77. package/bin/swl-telegram-bot.plist +21 -0
  78. package/bin/swl-telegram-bot.service +14 -0
  79. package/comandos/swl/.evolved.json +23 -0
  80. package/comandos/swl/actualizar.md +174 -0
  81. package/comandos/swl/adoptar-proyecto.md +207 -0
  82. package/comandos/swl/aprender.md +701 -0
  83. package/comandos/swl/auditar-deps.md +134 -0
  84. package/comandos/swl/autoresearch.md +170 -0
  85. package/comandos/swl/ayuda.md +224 -0
  86. package/comandos/swl/brainstorm.md +50 -0
  87. package/comandos/swl/checkpoint.md +330 -0
  88. package/comandos/swl/compactar.md +283 -0
  89. package/comandos/swl/configurar-ci.md +227 -0
  90. package/comandos/swl/contexto.md +112 -0
  91. package/comandos/swl/contribuir.md +233 -0
  92. package/comandos/swl/crear-skill.md +292 -0
  93. package/comandos/swl/cron.md +196 -0
  94. package/comandos/swl/dashboard.md +146 -0
  95. package/comandos/swl/discutir-fase.md +230 -0
  96. package/comandos/swl/ejecutar-fase.md +135 -0
  97. package/comandos/swl/evaluar-skill.md +487 -0
  98. package/comandos/swl/evolucion-estado.md +142 -0
  99. package/comandos/swl/evolucionar.md +259 -0
  100. package/comandos/swl/exportar-vault.md +189 -0
  101. package/comandos/swl/gateway.md +158 -0
  102. package/comandos/swl/inbox.md +116 -0
  103. package/comandos/swl/instalar.md +220 -0
  104. package/comandos/swl/instintos.md +86 -0
  105. package/comandos/swl/mapear-codebase.md +312 -0
  106. package/comandos/swl/mcp-status.md +175 -0
  107. package/comandos/swl/metricas.md +270 -0
  108. package/comandos/swl/modelo.md +102 -0
  109. package/comandos/swl/notificaciones.md +396 -0
  110. package/comandos/swl/nuevo-proyecto.md +154 -0
  111. package/comandos/swl/planear-fase.md +221 -0
  112. package/comandos/swl/plugins.md +256 -0
  113. package/comandos/swl/reflect-skills.md +125 -0
  114. package/comandos/swl/release.md +217 -0
  115. package/comandos/swl/revisar-impacto.md +206 -0
  116. package/comandos/swl/revisar.md +330 -0
  117. package/comandos/swl/salud.md +363 -0
  118. package/comandos/swl/sesiones.md +200 -0
  119. package/comandos/swl/skill-search.md +113 -0
  120. package/comandos/swl/verificar.md +585 -0
  121. package/comandos/swl/wiki.md +620 -0
  122. package/contextos/dev.md +32 -0
  123. package/contextos/research.md +30 -0
  124. package/contextos/review.md +31 -0
  125. package/habilidades/accesibilidad-a11y/SKILL.md +201 -0
  126. package/habilidades/accesibilidad-a11y/evals/evals.json +56 -0
  127. package/habilidades/accesibilidad-a11y/recursos/ejemplos-y-checklist-completo.md +441 -0
  128. package/habilidades/agent-browser/SKILL.md +218 -0
  129. package/habilidades/agentes-como-servicio/SKILL.md +218 -0
  130. package/habilidades/ai-runtime-security/SKILL.md +273 -0
  131. package/habilidades/angular-avanzado/SKILL.md +164 -0
  132. package/habilidades/angular-avanzado/recursos/ejemplos-avanzados.md +219 -0
  133. package/habilidades/angular-moderno/SKILL.md +186 -0
  134. package/habilidades/angular-moderno/evals/evals.json +45 -0
  135. package/habilidades/angular-moderno/recursos/ejemplos-avanzados.md +106 -0
  136. package/habilidades/api-rest-diseno/SKILL.md +191 -0
  137. package/habilidades/api-rest-diseno/recursos/openapi-template.yaml +506 -0
  138. package/habilidades/api-rest-diseno/recursos/referencia-api.md +140 -0
  139. package/habilidades/aprendizaje-continuo/SKILL.md +151 -0
  140. package/habilidades/aprendizaje-continuo/evals/evals.json +53 -0
  141. package/habilidades/aprendizaje-continuo/recursos/referencia-instintos.md +290 -0
  142. package/habilidades/async-python/SKILL.md +149 -0
  143. package/habilidades/async-python/evals/evals.json +47 -0
  144. package/habilidades/async-python/recursos/patrones-y-ejemplos-completos.md +292 -0
  145. package/habilidades/auth-patrones/.evolved.json +9 -0
  146. package/habilidades/auth-patrones/SKILL.md +413 -0
  147. package/habilidades/auth-patrones/recursos/implementaciones-completas.md +229 -0
  148. package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -0
  149. package/habilidades/auto-evolucion-protocolo/evals/evals.json +55 -0
  150. package/habilidades/auto-evolucion-protocolo/recursos/referencia-completa.md +145 -0
  151. package/habilidades/autoresearch/SKILL.md +268 -0
  152. package/habilidades/autoresearch/evals/evals.json +41 -0
  153. package/habilidades/autoresearch/recursos/checklist-template.md +191 -0
  154. package/habilidades/autoresearch/scripts/calcular-score.js +88 -0
  155. package/habilidades/azure-cloud/SKILL.md +308 -0
  156. package/habilidades/azure-cloud/recursos/aks.md +327 -0
  157. package/habilidades/backend-mcp-servidor/SKILL.md +270 -0
  158. package/habilidades/backend-production-resilience/SKILL.md +288 -0
  159. package/habilidades/brainstorming/SKILL.md +295 -0
  160. package/habilidades/brainstorming/recursos/componentes-html.md +247 -0
  161. package/habilidades/build-errors-cpp/SKILL.md +270 -0
  162. package/habilidades/build-errors-csharp/SKILL.md +265 -0
  163. package/habilidades/build-errors-go/SKILL.md +306 -0
  164. package/habilidades/build-errors-java/SKILL.md +278 -0
  165. package/habilidades/build-errors-kotlin/SKILL.md +303 -0
  166. package/habilidades/build-errors-nextjs/SKILL.md +312 -0
  167. package/habilidades/build-errors-php/SKILL.md +270 -0
  168. package/habilidades/build-errors-python/SKILL.md +292 -0
  169. package/habilidades/build-errors-rust/SKILL.md +284 -0
  170. package/habilidades/build-errors-swift/SKILL.md +272 -0
  171. package/habilidades/build-errors-typescript/SKILL.md +369 -0
  172. package/habilidades/checklist-calidad/SKILL.md +271 -0
  173. package/habilidades/checklist-calidad/recursos/quality-report-template.md +148 -0
  174. package/habilidades/checklist-seguridad/SKILL.md +285 -0
  175. package/habilidades/checkpoints-verificacion/SKILL.md +298 -0
  176. package/habilidades/checkpoints-verificacion/recursos/checkpoint-templates.md +360 -0
  177. package/habilidades/ci-cd-pipelines/SKILL.md +157 -0
  178. package/habilidades/ci-cd-pipelines/recursos/github-actions-template.yaml +403 -0
  179. package/habilidades/ci-cd-pipelines/recursos/pipelines-completos.md +487 -0
  180. package/habilidades/cloud-aws/SKILL.md +142 -0
  181. package/habilidades/cloud-aws/recursos/servicios-aws-referencia.md +321 -0
  182. package/habilidades/compactacion-contexto/SKILL.md +247 -0
  183. package/habilidades/contenedores-docker/SKILL.md +137 -0
  184. package/habilidades/contenedores-docker/recursos/dockerfile-template.dockerfile +160 -0
  185. package/habilidades/contenedores-docker/recursos/ejemplos-y-configuraciones.md +327 -0
  186. package/habilidades/context-builder/SKILL.md +170 -0
  187. package/habilidades/control-profundidad/SKILL.md +128 -0
  188. package/habilidades/csharp-experto/SKILL.md +322 -0
  189. package/habilidades/csharp-patrones/SKILL.md +316 -0
  190. package/habilidades/csharp-testing/SKILL.md +286 -0
  191. package/habilidades/css-moderno/SKILL.md +166 -0
  192. package/habilidades/css-moderno/evals/evals.json +43 -0
  193. package/habilidades/css-moderno/recursos/ejemplos-y-patrones-completos.md +337 -0
  194. package/habilidades/datos-etl/SKILL.md +129 -0
  195. package/habilidades/datos-etl/recursos/implementaciones-completas.md +322 -0
  196. package/habilidades/dbml-experto/SKILL.md +339 -0
  197. package/habilidades/dbml-experto/evals/evals.json +56 -0
  198. package/habilidades/dependencias-auditoria/SKILL.md +320 -0
  199. package/habilidades/deprecacion-migracion/SKILL.md +169 -0
  200. package/habilidades/deprecacion-migracion/recursos/implementaciones-completas.md +220 -0
  201. package/habilidades/design-tokens/SKILL.md +158 -0
  202. package/habilidades/design-tokens/recursos/tokens-y-configuracion.md +363 -0
  203. package/habilidades/devsecops-pipeline-security/SKILL.md +309 -0
  204. package/habilidades/diagrama-arquitectura/SKILL.md +165 -0
  205. package/habilidades/diagrama-arquitectura/assets/template.html +276 -0
  206. package/habilidades/discutir-fase/SKILL.md +188 -0
  207. package/habilidades/diseno-herramientas-agente/SKILL.md +199 -0
  208. package/habilidades/diseno-responsivo/SKILL.md +186 -0
  209. package/habilidades/diseno-responsivo/recursos/ejemplos-layouts.md +156 -0
  210. package/habilidades/django-experto/SKILL.md +205 -0
  211. package/habilidades/django-experto/recursos/async-django.md +390 -0
  212. package/habilidades/django-experto/recursos/drf-patrones.md +438 -0
  213. package/habilidades/django-experto/recursos/orm-avanzado.md +382 -0
  214. package/habilidades/django-experto/recursos/referencia-completa.md +188 -0
  215. package/habilidades/django-experto/recursos/testing-django.md +415 -0
  216. package/habilidades/doc-sync/SKILL.md +280 -0
  217. package/habilidades/drift-detection/SKILL.md +179 -0
  218. package/habilidades/ejecutar-fase/SKILL.md +468 -0
  219. package/habilidades/estilo-sin-ai-isms/SKILL.md +775 -0
  220. package/habilidades/estilo-sin-ai-isms/evals/evals.json +63 -0
  221. package/habilidades/estilo-sin-ai-isms/scripts/detectar_aiisms.py +500 -0
  222. package/habilidades/estructura-proyecto-claude/SKILL.md +215 -0
  223. package/habilidades/estructura-proyecto-claude/recursos/claude-md-template.md +261 -0
  224. package/habilidades/estructura-proyecto-claude/recursos/configuracion-y-extensiones.md +176 -0
  225. package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +289 -0
  226. package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +77 -0
  227. package/habilidades/estructura-proyecto-claude/recursos/variantes-por-stack.md +177 -0
  228. package/habilidades/evaluacion-agentes/SKILL.md +314 -0
  229. package/habilidades/event-driven/SKILL.md +153 -0
  230. package/habilidades/event-driven/recursos/implementaciones-completas.md +423 -0
  231. package/habilidades/extraccion-documentos/SKILL.md +221 -0
  232. package/habilidades/extractor-de-aprendizajes/.evolved.json +9 -0
  233. package/habilidades/extractor-de-aprendizajes/SKILL.md +311 -0
  234. package/habilidades/extractor-de-aprendizajes/evals/evals.json +55 -0
  235. package/habilidades/fastapi-experto/SKILL.md +221 -0
  236. package/habilidades/fastapi-experto/recursos/async-patterns.md +438 -0
  237. package/habilidades/fastapi-experto/recursos/dependency-injection.md +330 -0
  238. package/habilidades/fastapi-experto/recursos/referencia-completa.md +79 -0
  239. package/habilidades/fastapi-experto/recursos/testing-httpx.md +420 -0
  240. package/habilidades/filament-admin/SKILL.md +290 -0
  241. package/habilidades/frontend-avanzado/SKILL.md +257 -0
  242. package/habilidades/frontend-avanzado/recursos/apis-nativas-ejemplos.md +341 -0
  243. package/habilidades/gcp-cloud/SKILL.md +260 -0
  244. package/habilidades/gcp-cloud/recursos/gke.md +234 -0
  245. package/habilidades/gcp-cloud/recursos/terraform-gcp.md +307 -0
  246. package/habilidades/generacion-mermaid/SKILL.md +229 -0
  247. package/habilidades/git-worktrees-paralelo/SKILL.md +270 -0
  248. package/habilidades/go-experto/SKILL.md +305 -0
  249. package/habilidades/go-patrones/SKILL.md +299 -0
  250. package/habilidades/go-testing/SKILL.md +291 -0
  251. package/habilidades/graphql-experto/SKILL.md +323 -0
  252. package/habilidades/guardrail-semantico/SKILL.md +282 -0
  253. package/habilidades/harness-claude-code/SKILL.md +299 -0
  254. package/habilidades/iam-secretos/SKILL.md +265 -0
  255. package/habilidades/iam-secretos/recursos/implementaciones-completas.md +356 -0
  256. package/habilidades/infra-github-actions/SKILL.md +166 -0
  257. package/habilidades/instalar-sistema/.evolved.json +9 -0
  258. package/habilidades/instalar-sistema/SKILL.md +221 -0
  259. package/habilidades/java-experto/SKILL.md +290 -0
  260. package/habilidades/java-patrones/SKILL.md +275 -0
  261. package/habilidades/java-testing/SKILL.md +288 -0
  262. package/habilidades/kotlin-compose/SKILL.md +278 -0
  263. package/habilidades/kotlin-compose/recursos/animaciones-performance.md +93 -0
  264. package/habilidades/kotlin-experto/SKILL.md +318 -0
  265. package/habilidades/kotlin-testing/SKILL.md +267 -0
  266. package/habilidades/kotlin-testing/recursos/testing-avanzado.md +74 -0
  267. package/habilidades/kubernetes-orquestacion/SKILL.md +152 -0
  268. package/habilidades/kubernetes-orquestacion/recursos/manifiestos-completos.md +452 -0
  269. package/habilidades/langchain-langraph/SKILL.md +386 -0
  270. package/habilidades/langchain-langraph/recursos/evaluacion-rag.md +321 -0
  271. package/habilidades/langchain-langraph/recursos/rag-maturity-model.md +225 -0
  272. package/habilidades/langchain-langraph/recursos/vectorstores.md +306 -0
  273. package/habilidades/legacy-code-rescue/SKILL.md +267 -0
  274. package/habilidades/likec4-experto/SKILL.md +412 -0
  275. package/habilidades/likec4-experto/evals/evals.json +69 -0
  276. package/habilidades/manejo-errores/.evolved.json +9 -0
  277. package/habilidades/manejo-errores/SKILL.md +407 -0
  278. package/habilidades/manejo-errores/recursos/implementaciones-completas.md +248 -0
  279. package/habilidades/mapear-codebase/SKILL.md +275 -0
  280. package/habilidades/memoria-busqueda/SKILL.md +194 -0
  281. package/habilidades/memoria-busqueda/evals/evals.json +44 -0
  282. package/habilidades/meta-skills-estandar/SKILL.md +298 -0
  283. package/habilidades/meta-skills-estandar/recursos/anti-patrones-y-leyes.md +205 -0
  284. package/habilidades/meta-skills-estandar/recursos/frameworks-seguridad.md +107 -0
  285. package/habilidades/meta-skills-estandar/recursos/idiomas-framework.md +60 -0
  286. package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +163 -0
  287. package/habilidades/microservicios/SKILL.md +155 -0
  288. package/habilidades/microservicios/recursos/patrones-y-ejemplos-completos.md +325 -0
  289. package/habilidades/mobile-flutter/SKILL.md +199 -0
  290. package/habilidades/mobile-flutter/recursos/ejemplos-completos.md +319 -0
  291. package/habilidades/mobile-react-native/SKILL.md +176 -0
  292. package/habilidades/mobile-react-native/recursos/ejemplos-completos.md +216 -0
  293. package/habilidades/mongodb-experto/SKILL.md +302 -0
  294. package/habilidades/monitoring-alertas/SKILL.md +201 -0
  295. package/habilidades/monitoring-alertas/recursos/instrumentacion-y-alertas.md +301 -0
  296. package/habilidades/nestjs-experto/SKILL.md +307 -0
  297. package/habilidades/nestjs-experto/recursos/guards-interceptors.md +339 -0
  298. package/habilidades/nestjs-experto/recursos/modulos-di.md +287 -0
  299. package/habilidades/nestjs-experto/recursos/testing-nestjs.md +354 -0
  300. package/habilidades/nextjs-experto/SKILL.md +335 -0
  301. package/habilidades/nextjs-patrones/SKILL.md +303 -0
  302. package/habilidades/nextjs-testing/SKILL.md +331 -0
  303. package/habilidades/node-experto/.evolved.json +9 -0
  304. package/habilidades/node-experto/SKILL.md +266 -0
  305. package/habilidades/node-experto/recursos/patrones-completos.md +283 -0
  306. package/habilidades/notificaciones-multicanal/SKILL.md +159 -0
  307. package/habilidades/notificaciones-multicanal/recursos/config-template.json +115 -0
  308. package/habilidades/notificaciones-multicanal/recursos/configuracion-y-templates.md +303 -0
  309. package/habilidades/nuevo-proyecto/SKILL.md +204 -0
  310. package/habilidades/orquestacion-async/SKILL.md +303 -0
  311. package/habilidades/paid-media-tracking/SKILL.md +269 -0
  312. package/habilidades/paid-media-tracking/recursos/auditoria-tracking.md +220 -0
  313. package/habilidades/paid-media-tracking/recursos/google-ads-api.md +215 -0
  314. package/habilidades/patrones-python/SKILL.md +228 -0
  315. package/habilidades/patrones-python/evals/evals.json +56 -0
  316. package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -0
  317. package/habilidades/patrones-python/recursos/referencia-completa.md +202 -0
  318. package/habilidades/perfil-usuario/SKILL.md +200 -0
  319. package/habilidades/perfil-usuario/evals/evals.json +55 -0
  320. package/habilidades/performance-baseline/SKILL.md +297 -0
  321. package/habilidades/php-experto/SKILL.md +291 -0
  322. package/habilidades/php-patrones/SKILL.md +306 -0
  323. package/habilidades/php-testing/SKILL.md +280 -0
  324. package/habilidades/planear-fase/SKILL.md +269 -0
  325. package/habilidades/postgresql-experto/SKILL.md +151 -0
  326. package/habilidades/postgresql-experto/evals/evals.json +53 -0
  327. package/habilidades/postgresql-experto/recursos/referencia-completa.md +215 -0
  328. package/habilidades/prevencion-racionalizacion/SKILL.md +175 -0
  329. package/habilidades/prevencion-sobreingenieria/SKILL.md +323 -0
  330. package/habilidades/privacy-memoria/SKILL.md +141 -0
  331. package/habilidades/privacy-memoria/evals/evals.json +43 -0
  332. package/habilidades/prompt-engineering/SKILL.md +518 -0
  333. package/habilidades/prompt-engineering/recursos/patrones-avanzados.md +467 -0
  334. package/habilidades/rag-arquitectura/SKILL.md +338 -0
  335. package/habilidades/rails-experto/SKILL.md +237 -0
  336. package/habilidades/rails-experto/recursos/active-record.md +260 -0
  337. package/habilidades/rails-experto/recursos/hotwire-turbo.md +293 -0
  338. package/habilidades/rails-experto/recursos/testing-rspec.md +362 -0
  339. package/habilidades/react-experto/SKILL.md +209 -0
  340. package/habilidades/react-experto/evals/evals.json +55 -0
  341. package/habilidades/react-experto/recursos/patrones-y-ejemplos-completos.md +240 -0
  342. package/habilidades/react-optimizacion/SKILL.md +174 -0
  343. package/habilidades/react-optimizacion/recursos/patrones-avanzados.md +138 -0
  344. package/habilidades/redis-experto/SKILL.md +305 -0
  345. package/habilidades/release-semver/.evolved.json +9 -0
  346. package/habilidades/release-semver/SKILL.md +248 -0
  347. package/habilidades/release-semver/scripts/generar-changelog.sh +238 -0
  348. package/habilidades/rust-experto/SKILL.md +400 -0
  349. package/habilidades/rust-patrones/SKILL.md +296 -0
  350. package/habilidades/rust-testing/SKILL.md +311 -0
  351. package/habilidades/seguridad-skills-ia/SKILL.md +262 -0
  352. package/habilidades/sql-optimizacion/SKILL.md +200 -0
  353. package/habilidades/sql-optimizacion/evals/evals.json +54 -0
  354. package/habilidades/sql-optimizacion/recursos/patrones-sql-avanzados.md +131 -0
  355. package/habilidades/sre-patrones/SKILL.md +333 -0
  356. package/habilidades/sre-patrones/recursos/chaos-engineering.md +241 -0
  357. package/habilidades/sre-patrones/recursos/oncall-design.md +236 -0
  358. package/habilidades/stripe-pagos/SKILL.md +550 -0
  359. package/habilidades/stripe-pagos/recursos/errores-reintentos.md +390 -0
  360. package/habilidades/stripe-pagos/recursos/stripe-connect.md +290 -0
  361. package/habilidades/structured-outputs/SKILL.md +343 -0
  362. package/habilidades/swift-experto/SKILL.md +320 -0
  363. package/habilidades/swift-experto/recursos/keychain-y-wrappers.md +110 -0
  364. package/habilidades/swift-patrones/SKILL.md +313 -0
  365. package/habilidades/swift-patrones/recursos/tca-ejemplo-completo.md +113 -0
  366. package/habilidades/swift-testing/SKILL.md +254 -0
  367. package/habilidades/swift-testing/recursos/xcuitest-planes.md +143 -0
  368. package/habilidades/swl-dashboard/SKILL.md +370 -0
  369. package/habilidades/swl-markitdown/SKILL.md +285 -0
  370. package/habilidades/swl-markitdown/evals/evals.json +52 -0
  371. package/habilidades/swl-revisar-impacto/SKILL.md +233 -0
  372. package/habilidades/tailwind-experto/SKILL.md +240 -0
  373. package/habilidades/tailwind-experto/recursos/referencia-completa.md +184 -0
  374. package/habilidades/tdd-workflow/SKILL.md +293 -0
  375. package/habilidades/terraform-experto/SKILL.md +321 -0
  376. package/habilidades/testing-python/SKILL.md +340 -0
  377. package/habilidades/testing-python/recursos/ejemplos-completos.md +167 -0
  378. package/habilidades/threat-model-lite/SKILL.md +246 -0
  379. package/habilidades/tracing-processor/SKILL.md +212 -0
  380. package/habilidades/tracking-measurement/SKILL.md +239 -0
  381. package/habilidades/tracking-measurement/recursos/consent-mode.md +231 -0
  382. package/habilidades/tracking-measurement/recursos/gtm-datalayer.md +216 -0
  383. package/habilidades/tracking-measurement/recursos/meta-capi.md +262 -0
  384. package/habilidades/typescript-avanzado/SKILL.md +144 -0
  385. package/habilidades/typescript-avanzado/evals/evals.json +55 -0
  386. package/habilidades/typescript-avanzado/recursos/patrones-y-ejemplos-completos.md +298 -0
  387. package/habilidades/typescript-diagnosticos/SKILL.md +513 -0
  388. package/habilidades/ux-diseno/SKILL.md +116 -0
  389. package/habilidades/ux-diseno/evals/evals.json +43 -0
  390. package/habilidades/ux-diseno/recursos/patrones-ux-referencia.md +214 -0
  391. package/habilidades/validacion-ci-sistema/SKILL.md +136 -0
  392. package/habilidades/validacion-ci-sistema/recursos/validadores-completos.md +369 -0
  393. package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +286 -0
  394. package/habilidades/verificacion-evidencia/SKILL.md +160 -0
  395. package/habilidades/verificar-trabajo/SKILL.md +303 -0
  396. package/habilidades/verificar-trabajo/recursos/plantilla-verificacion.md +60 -0
  397. package/habilidades/wiki-conocimiento/SKILL.md +276 -0
  398. package/habilidades/wireframes-flujos/SKILL.md +212 -0
  399. package/habilidades/wireframes-flujos/recursos/referencia-completa.md +192 -0
  400. package/habilidades/workflow-claude-code/SKILL.md +260 -0
  401. package/habilidades/workflow-claude-code/recursos/referencia-completa.md +109 -0
  402. package/hooks/_run-hook.sh +57 -0
  403. package/hooks/actualizar-perfil-usuario.js +364 -0
  404. package/hooks/agente-lifecycle.js +71 -0
  405. package/hooks/aiisms-detector.js +173 -0
  406. package/hooks/audit-trail.js +204 -0
  407. package/hooks/auto-background.js +97 -0
  408. package/hooks/auto-consolidacion.js +178 -0
  409. package/hooks/auto-evolucion.js +666 -0
  410. package/hooks/auto-restaurar-settings.js +360 -0
  411. package/hooks/calidad-pre-commit.js +929 -0
  412. package/hooks/calidad-typescript.js +511 -0
  413. package/hooks/captura-feedback-usuario.js +148 -0
  414. package/hooks/check-update.js +211 -0
  415. package/hooks/clasificador-mensajes.js +271 -0
  416. package/hooks/degradacion-instintos.js +272 -0
  417. package/hooks/escaneo-secretos.js +389 -0
  418. package/hooks/extraccion-aprendizajes.js +763 -0
  419. package/hooks/grafo-contexto.js +129 -0
  420. package/hooks/graph-update.js +67 -0
  421. package/hooks/guardrail-modelo.js +247 -0
  422. package/hooks/inbox-aviso.js +75 -0
  423. package/hooks/inyeccion-contexto.js +246 -0
  424. package/hooks/lib/abort-registry.js +214 -0
  425. package/hooks/lib/agent-backend.js +210 -0
  426. package/hooks/lib/agent-comms.js +263 -0
  427. package/hooks/lib/agent-issue-codes.js +284 -0
  428. package/hooks/lib/agent-matcher.js +189 -0
  429. package/hooks/lib/async-hook-registry.js +252 -0
  430. package/hooks/lib/atomic-write.js +130 -0
  431. package/hooks/lib/auto-consolidator.js +335 -0
  432. package/hooks/lib/canary-skills.js +187 -0
  433. package/hooks/lib/consolidation-lock.js +291 -0
  434. package/hooks/lib/context-builder.js +430 -0
  435. package/hooks/lib/context-compressor.js +657 -0
  436. package/hooks/lib/convergence-detector.js +105 -0
  437. package/hooks/lib/delegation-tracker.js +198 -0
  438. package/hooks/lib/detectar-package-manager.js +423 -0
  439. package/hooks/lib/edit-accumulator.js +171 -0
  440. package/hooks/lib/error-classifier.js +308 -0
  441. package/hooks/lib/event-bus.js +112 -0
  442. package/hooks/lib/evolution-tracker.js +442 -0
  443. package/hooks/lib/execution-state.js +316 -0
  444. package/hooks/lib/fingerprint-id.js +135 -0
  445. package/hooks/lib/gateway-notify.js +116 -0
  446. package/hooks/lib/graph-security.js +75 -0
  447. package/hooks/lib/guardrail-metrics.js +202 -0
  448. package/hooks/lib/hook-circuit-breaker.js +206 -0
  449. package/hooks/lib/loop-detector.js +267 -0
  450. package/hooks/lib/mcp-health.js +184 -0
  451. package/hooks/lib/mcp-pool.js +436 -0
  452. package/hooks/lib/memory-search.js +506 -0
  453. package/hooks/lib/merkle-audit.js +96 -0
  454. package/hooks/lib/model-router.js +222 -0
  455. package/hooks/lib/normalize-error.js +324 -0
  456. package/hooks/lib/normalize-input.js +65 -0
  457. package/hooks/lib/nudge-tracker.js +306 -0
  458. package/hooks/lib/otlp-exporter.js +365 -0
  459. package/hooks/lib/performance-marks.js +239 -0
  460. package/hooks/lib/privacy-filter.js +128 -0
  461. package/hooks/lib/prompt-injection-scanner.js +209 -0
  462. package/hooks/lib/provenance-tracker.js +183 -0
  463. package/hooks/lib/rate-limit-tracker.js +253 -0
  464. package/hooks/lib/reflect-classifier.js +164 -0
  465. package/hooks/lib/resource-quota.js +122 -0
  466. package/hooks/lib/retry-jitter.js +165 -0
  467. package/hooks/lib/risk-engine.js +368 -0
  468. package/hooks/lib/run-log.js +408 -0
  469. package/hooks/lib/session-fts.js +379 -0
  470. package/hooks/lib/session-store.js +293 -0
  471. package/hooks/lib/singleton-guard.js +159 -0
  472. package/hooks/lib/skill-auditor.js +588 -0
  473. package/hooks/lib/sync-status.js +228 -0
  474. package/hooks/lib/taint-tracker.js +107 -0
  475. package/hooks/lib/task-service.js +295 -0
  476. package/hooks/lib/tech-skills-map.js +146 -0
  477. package/hooks/lib/telegram-cliente.js +159 -0
  478. package/hooks/lib/telegram-config.js +170 -0
  479. package/hooks/lib/token-budget.js +156 -0
  480. package/hooks/lib/token-estimator.js +420 -0
  481. package/hooks/lib/toon-compressor.js +245 -0
  482. package/hooks/lib/usage-model.js +183 -0
  483. package/hooks/lib/variable-resolver.js +230 -0
  484. package/hooks/linea-estado.js +324 -0
  485. package/hooks/metricas-evolucion.js +209 -0
  486. package/hooks/monitor-contexto.js +325 -0
  487. package/hooks/notificacion-sesion-stop.js +198 -0
  488. package/hooks/notificacion-telegram-notification.js +4 -0
  489. package/hooks/notificacion-telegram-subagent.js +4 -0
  490. package/hooks/notificacion-telegram.js +267 -0
  491. package/hooks/preservar-estado-pre-compact.js +150 -0
  492. package/hooks/proteccion-rutas.js +366 -0
  493. package/hooks/registro-turnos.js +209 -0
  494. package/hooks/resumen-sesion.js +249 -0
  495. package/hooks/risk-scoring.js +323 -0
  496. package/hooks/rotar-audit-auto.js +122 -0
  497. package/hooks/sugerir-regenerar-inventario.js +170 -0
  498. package/hooks/telemetria-agentes.js +167 -0
  499. package/hooks/tracking-costos.js +688 -0
  500. package/instintos/global.yaml +8 -0
  501. package/instintos/perfil-usuario.yaml +53 -0
  502. package/instintos/prompt-appendices.yaml +57 -0
  503. package/instintos/proyecto.yaml +372 -0
  504. package/manifiestos/gateway-config.json +77 -0
  505. package/manifiestos/handoff-context.json +223 -0
  506. package/manifiestos/hook-profiles.json +44 -0
  507. package/manifiestos/hooks-config.json +360 -0
  508. package/manifiestos/modulos.json +1173 -0
  509. package/manifiestos/perfiles.json +404 -0
  510. package/package.json +86 -0
  511. package/plantillas/ESTADO.md +109 -0
  512. package/plantillas/HOJA-RUTA.md +143 -0
  513. package/plantillas/PROYECTO.md +122 -0
  514. package/plantillas/REQUISITOS.md +132 -0
  515. package/plantillas/auditor-veto-template.md +105 -0
  516. package/plantillas/github-workflows/README.md +47 -0
  517. package/plantillas/github-workflows/release-please.yml +44 -0
  518. package/plantillas/github-workflows/swl-ci.yml +107 -0
  519. package/plantillas/github-workflows/swl-security.yml +51 -0
  520. package/plantillas/mcp-mineru.json +13 -0
  521. package/plantillas/research/ARQUITECTURA.md +220 -0
  522. package/plantillas/research/FUNCIONALIDADES.md +175 -0
  523. package/plantillas/research/RESUMEN.md +165 -0
  524. package/plantillas/research/STACK.md +233 -0
  525. package/plantillas/research/TRAMPAS.md +299 -0
  526. package/plantillas/skill-evals-template.json +44 -0
  527. package/plugin.json +343 -0
  528. package/reglas/accesibilidad.md +269 -0
  529. package/reglas/api-diseno.md +400 -0
  530. package/reglas/arquitectura.md +352 -0
  531. package/reglas/brevedad-output.md +124 -0
  532. package/reglas/cloud-infra.md +247 -0
  533. package/reglas/docs.md +245 -0
  534. package/reglas/estilo-codigo.md +201 -0
  535. package/reglas/git-workflow.md +245 -0
  536. package/reglas/gobernanza.md +271 -0
  537. package/reglas/harness-claude-code.md +213 -0
  538. package/reglas/hooks.md +186 -0
  539. package/reglas/lenguajes/csharp/estilo-codigo.md +231 -0
  540. package/reglas/lenguajes/csharp/hooks.md +281 -0
  541. package/reglas/lenguajes/csharp/patrones.md +226 -0
  542. package/reglas/lenguajes/csharp/seguridad.md +258 -0
  543. package/reglas/lenguajes/csharp/testing.md +176 -0
  544. package/reglas/lenguajes/go/estilo-codigo.md +195 -0
  545. package/reglas/lenguajes/go/hooks.md +249 -0
  546. package/reglas/lenguajes/go/patrones.md +249 -0
  547. package/reglas/lenguajes/go/seguridad.md +225 -0
  548. package/reglas/lenguajes/go/testing.md +272 -0
  549. package/reglas/lenguajes/java/estilo-codigo.md +217 -0
  550. package/reglas/lenguajes/java/hooks.md +251 -0
  551. package/reglas/lenguajes/java/patrones.md +226 -0
  552. package/reglas/lenguajes/java/seguridad.md +233 -0
  553. package/reglas/lenguajes/java/testing.md +238 -0
  554. package/reglas/lenguajes/kotlin/estilo-codigo.md +208 -0
  555. package/reglas/lenguajes/kotlin/hooks.md +245 -0
  556. package/reglas/lenguajes/kotlin/patrones.md +201 -0
  557. package/reglas/lenguajes/kotlin/seguridad.md +202 -0
  558. package/reglas/lenguajes/kotlin/testing.md +236 -0
  559. package/reglas/lenguajes/nextjs/estilo-codigo.md +175 -0
  560. package/reglas/lenguajes/nextjs/hooks.md +186 -0
  561. package/reglas/lenguajes/nextjs/patrones.md +225 -0
  562. package/reglas/lenguajes/nextjs/seguridad.md +216 -0
  563. package/reglas/lenguajes/nextjs/testing.md +193 -0
  564. package/reglas/lenguajes/php/estilo-codigo.md +228 -0
  565. package/reglas/lenguajes/php/hooks.md +165 -0
  566. package/reglas/lenguajes/php/patrones.md +233 -0
  567. package/reglas/lenguajes/php/seguridad.md +186 -0
  568. package/reglas/lenguajes/php/testing.md +205 -0
  569. package/reglas/lenguajes/rust/estilo-codigo.md +207 -0
  570. package/reglas/lenguajes/rust/hooks.md +240 -0
  571. package/reglas/lenguajes/rust/patrones.md +250 -0
  572. package/reglas/lenguajes/rust/seguridad.md +221 -0
  573. package/reglas/lenguajes/rust/testing.md +194 -0
  574. package/reglas/lenguajes/swift/estilo-codigo.md +238 -0
  575. package/reglas/lenguajes/swift/hooks.md +257 -0
  576. package/reglas/lenguajes/swift/patrones.md +235 -0
  577. package/reglas/lenguajes/swift/seguridad.md +248 -0
  578. package/reglas/lenguajes/swift/testing.md +242 -0
  579. package/reglas/markitdown.md +60 -0
  580. package/reglas/memoria-consolidada.md +209 -0
  581. package/reglas/patrones.md +225 -0
  582. package/reglas/performance.md +195 -0
  583. package/reglas/pruebas.md +159 -0
  584. package/reglas/seguridad-agentes.md +351 -0
  585. package/reglas/seguridad.md +151 -0
  586. package/reglas/skills-estandar.md +373 -0
  587. package/reglas/testing.md +193 -0
  588. package/schemas/agent-contract.json +176 -0
  589. package/schemas/agent-frontmatter.schema.json +149 -0
  590. package/schemas/agent-message.schema.json +53 -0
  591. package/schemas/agent-output-implementacion.schema.json +85 -0
  592. package/schemas/agent-output-planificacion.schema.json +113 -0
  593. package/schemas/agent-output-review.schema.json +78 -0
  594. package/schemas/diary-entry.schema.json +80 -0
  595. package/schemas/hook-profiles.schema.json +39 -0
  596. package/schemas/hooks-config.schema.json +74 -0
  597. package/schemas/instinct.schema.json +115 -0
  598. package/schemas/modulos.schema.json +29 -0
  599. package/schemas/perfiles.schema.json +28 -0
  600. package/schemas/plugin.schema.json +64 -0
  601. package/schemas/skill-evals.schema.json +95 -0
  602. package/schemas/skill-frontmatter.schema.json +170 -0
  603. package/scripts/actualizar.js +145 -0
  604. package/scripts/audit-skills.sh +78 -0
  605. package/scripts/auditar-agentes-gaps.js +149 -0
  606. package/scripts/auditar-cobertura-frameworks.js +241 -0
  607. package/scripts/auditar-skills-gaps.js +206 -0
  608. package/scripts/bootstrap-instintos.js +259 -0
  609. package/scripts/check-update.js +109 -0
  610. package/scripts/comandos/agents.js +105 -0
  611. package/scripts/comandos/info.js +108 -0
  612. package/scripts/comandos/install-asistido.js +186 -0
  613. package/scripts/comandos/skills.js +211 -0
  614. package/scripts/configurar-branch-protection.js +418 -0
  615. package/scripts/daemon-swl.py +388 -0
  616. package/scripts/desinstalar.js +130 -0
  617. package/scripts/doctor.js +559 -0
  618. package/scripts/field-report.js +199 -0
  619. package/scripts/generar-inventario.js +317 -0
  620. package/scripts/inbox-tmux-inject.js +161 -0
  621. package/scripts/inferir-herramientas-permitidas.js +586 -0
  622. package/scripts/inicializar.js +133 -0
  623. package/scripts/instalador.js +1031 -0
  624. package/scripts/instalar-git-hook.js +122 -0
  625. package/scripts/lib/agp-frontmatter.js +222 -0
  626. package/scripts/lib/append-con-marcadores.js +199 -0
  627. package/scripts/lib/artefactos-python.js +43 -0
  628. package/scripts/lib/audit-query.js +221 -0
  629. package/scripts/lib/autostart-linux.js +347 -0
  630. package/scripts/lib/autostart-macos.js +360 -0
  631. package/scripts/lib/autostart-windows.js +307 -0
  632. package/scripts/lib/budget-enforcer.js +252 -0
  633. package/scripts/lib/claude-sessions.js +285 -0
  634. package/scripts/lib/configurar-ci.js +380 -0
  635. package/scripts/lib/console-span-exporter.js +92 -0
  636. package/scripts/lib/contadores-inventario.js +217 -0
  637. package/scripts/lib/dashboard-widgets.js +290 -0
  638. package/scripts/lib/detectar-runtime.js +279 -0
  639. package/scripts/lib/detectar-stack.js +187 -0
  640. package/scripts/lib/diary-entry.js +234 -0
  641. package/scripts/lib/drift-detector.js +545 -0
  642. package/scripts/lib/estado.js +124 -0
  643. package/scripts/lib/gestor-componentes.js +243 -0
  644. package/scripts/lib/gitignore-manifest.js +305 -0
  645. package/scripts/lib/graph-analyze.py +556 -0
  646. package/scripts/lib/graph-builder.py +485 -0
  647. package/scripts/lib/graph-cluster.py +259 -0
  648. package/scripts/lib/health-row.js +168 -0
  649. package/scripts/lib/hooks-settings.js +789 -0
  650. package/scripts/lib/manifiestos.js +138 -0
  651. package/scripts/lib/mc-client.js +137 -0
  652. package/scripts/lib/notificaciones-telegram.js +1107 -0
  653. package/scripts/lib/npm-version.js +261 -0
  654. package/scripts/lib/paquetes-conocidos.js +50 -0
  655. package/scripts/lib/preservar-usuario.js +586 -0
  656. package/scripts/lib/prompt-builder.js +264 -0
  657. package/scripts/lib/resolver-externo.js +332 -0
  658. package/scripts/lib/schedule-parser.js +305 -0
  659. package/scripts/lib/scoring-instintos.js +240 -0
  660. package/scripts/lib/seguridad.js +160 -0
  661. package/scripts/lib/selector-interactivo.js +152 -0
  662. package/scripts/lib/semantic-search.js +242 -0
  663. package/scripts/lib/skill-discovery.js +234 -0
  664. package/scripts/lib/skill-metrics.js +246 -0
  665. package/scripts/lib/skill-normalizer.js +112 -0
  666. package/scripts/lib/skills-hub.js +340 -0
  667. package/scripts/lib/span-schema.js +134 -0
  668. package/scripts/lib/tool-cost-analyzer.js +255 -0
  669. package/scripts/lib/tracing-processor-interface.js +286 -0
  670. package/scripts/lib/transformadores/base.js +80 -0
  671. package/scripts/lib/transformadores/claude.js +124 -0
  672. package/scripts/lib/transformadores/codex.js +115 -0
  673. package/scripts/lib/transformadores/copilot.js +106 -0
  674. package/scripts/lib/transformadores/gemini.js +74 -0
  675. package/scripts/lib/transformadores/index.js +35 -0
  676. package/scripts/lib/transformadores/opencode.js +75 -0
  677. package/scripts/lib/ui.js +259 -0
  678. package/scripts/limpiar-artefactos-python.js +131 -0
  679. package/scripts/mcp-orchestrator.py +386 -0
  680. package/scripts/mcp-pool-manager.py +352 -0
  681. package/scripts/mcp-telemetry.py +378 -0
  682. package/scripts/poblar-evolvable.js +226 -0
  683. package/scripts/publicar.js +287 -0
  684. package/scripts/reflect-skills.js +403 -0
  685. package/scripts/rotar-audit-logs.js +185 -0
  686. package/scripts/run-skill-evals.js +242 -0
  687. package/scripts/smoke-test.js +374 -0
  688. package/scripts/token-analysis.py +471 -0
  689. package/scripts/validar-manifest.js +195 -0
  690. package/scripts/validar-memoria.js +321 -0
  691. package/scripts/validar-tests-aislamiento.js +184 -0
  692. package/scripts/validar-tokens-test.js +208 -0
  693. package/scripts/validar.js +147 -0
  694. package/scripts/validate-markdown.py +339 -0
  695. package/scripts/validate-skills.py +385 -0
  696. package/scripts/vendor/claude-usage/README.md +116 -0
  697. package/scripts/vendor/claude-usage/cli.py +334 -0
  698. package/scripts/vendor/claude-usage/dashboard.py +795 -0
  699. package/scripts/vendor/claude-usage/scanner.py +467 -0
  700. package/scripts/vendor/markitdown/cli.py +194 -0
  701. package/scripts/verificar-evolucion.js +289 -0
  702. package/scripts/verificar-release.js +494 -0
@@ -0,0 +1,265 @@
1
+ ---
2
+ name: iam-secretos
3
+ description: >
4
+ Identity and Access Management y gestión de secretos: RBAC, ABAC, HashiCorp Vault,
5
+ AWS Secrets Manager, Azure Key Vault, rotación de secretos, principio de mínimo
6
+ privilegio, cuentas de servicio, gestión de API keys, zero trust.
7
+ version: "1.1.0"
8
+ evolved: true
9
+ evolved-from: "1.0.0"
10
+ evolved-at: "2026-04-24"
11
+ evolved-by: "aprender"
12
+ evolved-note: "Sección nueva: logs con PII → gitignore + hard-block env flag en producción (defense in depth)"
13
+ herramientasPermitidas: [Read, Grep]
14
+ evolvable: true # default para skill estandar
15
+ nist_csf: [PR.AA-01, PR.AA-02, PR.AA-05, PR.DS-02]
16
+ attack_techniques: [T1552, T1078]
17
+ d3fend_techniques: [D3-MFA]
18
+ exclusiones:
19
+ - "No cargar para autenticación y autorización de usuarios en el frontend (login, JWT en browser, OAuth PKCE) — para auth de usuario final cargar `auth-patrones`."
20
+ - "No cargar para configuración de IAM en nubes específicas (AWS IAM roles, GCP Service Accounts, Azure Managed Identity) sin relación con la aplicación — para cloud IAM cargar el skill de la nube correspondiente (`cloud-aws`, `gcp-cloud`, `azure-cloud`)."
21
+ - "No cargar para auditoría de dependencias con CVEs (vulnerabilidades en paquetes npm/pip) — para auditoría de dependencias cargar `dependencias-auditoria`."
22
+ - "No cargar para cifrado de datos en reposo o en tránsito sin relación con secretos o identidades (TLS, AES en columnas de BD) — para cifrado de datos cargar el skill de seguridad del stack correspondiente."
23
+ ---
24
+ # IAM y Gestión de Secretos — Guía de Producción
25
+
26
+ ## Cuándo NO cargar
27
+
28
+ - La tarea es autenticación de usuario en el frontend (login, JWT en browser, OAuth PKCE): cargar `auth-patrones`.
29
+ - La tarea es configuración de IAM en la nube (AWS IAM, GCP Service Accounts, Azure Managed Identity) sin relación con la aplicación: cargar el skill de la nube correspondiente.
30
+ - La tarea es auditoría de CVEs en paquetes de dependencias: cargar `dependencias-auditoria`.
31
+ - La tarea es cifrado de datos en reposo o en tránsito sin relación con identidades o secretos: cargar el skill de seguridad del stack.
32
+
33
+ ## Principios Base
34
+
35
+ ### Zero Trust — "Nunca confíes, siempre verifica"
36
+
37
+ ```
38
+ Modelo perimetral tradicional: Modelo Zero Trust:
39
+ [Firewall externo] Toda petición se autentica
40
+ └── Interior "seguro" Toda petición se autoriza
41
+ └── Sin verificación Acceso mínimo siempre
42
+ Red, identidad y datos cifrados
43
+ ```
44
+
45
+ **Reglas de oro:**
46
+ 1. Ningún secreto en código fuente, variables de entorno de CI/CD, ni logs.
47
+ 2. Todo acceso privilegiado tiene duración máxima y se rota periódicamente.
48
+ 3. Las cuentas de servicio tienen permisos mínimos necesarios (least privilege).
49
+ 4. Toda acción privilegiada deja registro de auditoría.
50
+
51
+ ---
52
+
53
+ ## RBAC — Control de Acceso Basado en Roles
54
+
55
+ ```python
56
+ from enum import Enum
57
+ from typing import FrozenSet
58
+
59
+
60
+ class Permiso(str, Enum):
61
+ USUARIO_LEER = "usuario:leer"
62
+ USUARIO_CREAR = "usuario:crear"
63
+ USUARIO_EDITAR = "usuario:editar"
64
+ USUARIO_ELIMINAR = "usuario:eliminar"
65
+ REPORTE_LEER = "reporte:leer"
66
+ REPORTE_EXPORTAR = "reporte:exportar"
67
+ ADMIN_CONFIGURAR = "admin:configurar"
68
+ ADMIN_AUDITAR = "admin:auditar"
69
+
70
+
71
+ class Rol(str, Enum):
72
+ LECTURA = "LECTURA"
73
+ OPERADOR = "OPERADOR"
74
+ ADMIN = "ADMIN"
75
+ AUDITOR = "AUDITOR"
76
+ SUPER = "SUPER"
77
+
78
+
79
+ PERMISOS_POR_ROL: dict[Rol, FrozenSet[Permiso]] = {
80
+ Rol.LECTURA: frozenset({Permiso.USUARIO_LEER, Permiso.REPORTE_LEER}),
81
+ Rol.OPERADOR: frozenset({
82
+ Permiso.USUARIO_LEER, Permiso.USUARIO_CREAR, Permiso.USUARIO_EDITAR,
83
+ Permiso.REPORTE_LEER, Permiso.REPORTE_EXPORTAR,
84
+ }),
85
+ Rol.ADMIN: frozenset({
86
+ Permiso.USUARIO_LEER, Permiso.USUARIO_CREAR, Permiso.USUARIO_EDITAR,
87
+ Permiso.USUARIO_ELIMINAR, Permiso.REPORTE_LEER,
88
+ Permiso.REPORTE_EXPORTAR, Permiso.ADMIN_CONFIGURAR,
89
+ }),
90
+ Rol.AUDITOR: frozenset({Permiso.USUARIO_LEER, Permiso.REPORTE_LEER, Permiso.ADMIN_AUDITAR}),
91
+ Rol.SUPER: frozenset(Permiso),
92
+ }
93
+
94
+
95
+ def requiere_permiso(permiso: Permiso):
96
+ """Decorador FastAPI para verificación de permisos granulares."""
97
+ from fastapi import Depends, HTTPException, status
98
+
99
+ def verificar(usuario=Depends(get_current_user)):
100
+ if permiso not in PERMISOS_POR_ROL.get(usuario.rol, frozenset()):
101
+ raise HTTPException(
102
+ status_code=status.HTTP_403_FORBIDDEN,
103
+ detail={"permiso_requerido": permiso.value, "rol_actual": usuario.rol.value},
104
+ )
105
+ return usuario
106
+
107
+ return Depends(verificar)
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Anti-Patrones de IAM y Secretos
113
+
114
+ | Anti-patrón | Riesgo | Solución |
115
+ |-------------|--------|----------|
116
+ | Secretos en variables de entorno del proceso | Visibles en `/proc/environ` | Usar Vault/AWS SM con acceso programático |
117
+ | Secretos en código fuente o Git | Exposición permanente | Detección con `git-secrets`, `truffleHog` en CI |
118
+ | Credenciales de larga duración sin rotación | Ventana de ataque infinita | Credenciales dinámicas o rotación automática |
119
+ | Rol de servicio con permisos de admin | Un compromiso = acceso total | Least privilege: solo los permisos necesarios |
120
+ | API keys sin expiración ni scopes | Key comprometida da acceso total | Expiración obligatoria + scopes granulares |
121
+ | Logs que contienen secretos | Secretos filtrados en logs | Nunca loguear headers de Authorization ni tokens |
122
+ | Sin auditoría de acceso a secretos | Sin visibilidad | Habilitar audit logs en Vault/AWS SM |
123
+
124
+ ---
125
+
126
+ ## Implementaciones Completas
127
+
128
+ Para implementaciones de ABAC, HashiCorp Vault, AWS Secrets Manager con caché,
129
+ gestión de API Keys, estrategias de rotación de secretos y configuración de
130
+ cuentas de servicio en Kubernetes, ver
131
+ [recursos/implementaciones-completas.md](recursos/implementaciones-completas.md).
132
+
133
+ ---
134
+
135
+ ## Checklist de Revisión — IAM y Secretos
136
+
137
+ - [ ] Cero secretos en código fuente, `.env` de producción, o CI/CD variables sin cifrar.
138
+ - [ ] Toda cuenta de servicio tiene permisos mínimos (least privilege).
139
+ - [ ] Los secretos se leen de Vault/AWS SM en tiempo de ejecución, no en tiempo de build.
140
+ - [ ] Las API keys se almacenan sólo como hash (SHA-256), nunca en texto plano.
141
+ - [ ] Hay un plan de rotación documentado con frecuencia para cada tipo de secreto.
142
+ - [ ] El acceso a recursos sensibles pasa por verificación ABAC (no sólo RBAC) donde aplica.
143
+ - [ ] Los audit logs de acceso a secretos están habilitados y retenidos por 1 año mínimo.
144
+ - [ ] Los Kubernetes ServiceAccounts tienen RBAC restringido a sus propios recursos.
145
+ - [ ] Los certificados TLS tienen alerta de expiración 30 días antes.
146
+ - [ ] El código tiene pruebas que verifican que usuarios sin rol no pueden acceder a recursos protegidos.
147
+
148
+ ## Gotchas / Errores comunes no obvios
149
+
150
+ **Las variables de entorno de proceso no son más seguras que los archivos `.env` en contenedores Docker porque `docker inspect` expone todas las variables de entorno en texto plano**: configurar secretos con `-e DATABASE_PASSWORD=secreto` en `docker run` o en `docker-compose.yml` los hace visibles para cualquiera con acceso al daemon Docker (`docker inspect <container>`). Causa: las variables de entorno de proceso en Linux son visibles en `/proc/<pid>/environ` y en la API de Docker sin autenticación adicional. Fix: usar Docker Secrets (`docker secret create`) o montar el secreto como archivo en un volumen `tmpfs` y leerlo desde el código, nunca como variable de entorno de proceso.
151
+
152
+ **HashiCorp Vault con `AppRole` en CI/CD usa el mismo `role_id` + `secret_id` para todos los pipelines, eliminando la trazabilidad de auditoría**: si el `secret_id` es estático y compartido entre todos los jobs de CI, el audit log de Vault solo muestra "appRole autenticó" sin identificar cuál pipeline específico accedió al secreto. Causa: el propósito de `AppRole` es autenticación por instancia, pero se usa como credencial global. Fix: usar `secret_id` de un solo uso (`use_limit=1`) generado por cada job de CI al inicio del pipeline con un `wrapped token`. Esto garantiza trazabilidad y elimina la ventana de reutilización.
153
+
154
+ **La rotación automática de secretos en AWS Secrets Manager puede romper conexiones de larga duración a la BD que no leen el secreto en cada conexión**: las aplicaciones que leen `DATABASE_URL` una sola vez al arrancar y la cachean en memoria durante la vida del proceso siguen usando la credencial antigua después de la rotación. Causa: AWS SM rota el secreto pero no reinicia la aplicación ni invalida el caché del proceso. Fix: implementar un mecanismo de reconexión que re-lee el secreto desde SM cuando la BD devuelve un error de autenticación (código `PGCONN_ERROR` en PostgreSQL o `ER_ACCESS_DENIED_ERROR` en MySQL). No cachear la URL de conexión más allá de la frecuencia de rotación.
155
+
156
+ **RBAC implementado solo en el frontend produce IDOR (Insecure Direct Object Reference) cuando los endpoints no validan permisos server-side**: si el botón "Eliminar" se oculta en la UI para usuarios sin el rol `ADMIN` pero el endpoint `DELETE /api/usuarios/:id` no verifica el rol del JWT, cualquier usuario autenticado puede enviar el request directamente con curl y eliminará el registro. Causa: la verificación de RBAC en el frontend es UX, no seguridad. Fix: el decorador `requiere_permiso(Permiso.USUARIO_ELIMINAR)` o equivalente DEBE estar en CADA endpoint mutante, sin excepción. Verificar en code review que no hay endpoint de escritura sin `Depends(require_role([...]))` en FastAPI o equivalente en el framework del stack.
157
+
158
+ ---
159
+
160
+ ## Logs con PII: gitignore + hard-block env flag en producción (defense in depth)
161
+
162
+ ### Regla
163
+
164
+ Cuando la aplicación tiene capacidad de loggear contenido que puede incluir
165
+ PII (prompts de usuario, payloads de request, body de webhooks de terceros,
166
+ stack traces con datos concretos), aplicar **defensa en profundidad** con dos
167
+ capas independientes:
168
+
169
+ 1. **Capa 1 — Infraestructura**: `logs/*.jsonl` (o el path equivalente) fuera
170
+ del tracking de git via `.gitignore`. Previene fuga accidental al publicar
171
+ el repo.
172
+ 2. **Capa 2 — Runtime**: flag de feature (`llm_prompt_audit_log_text=True` o
173
+ similar) que **rechaza duro** en producción, sin importar si la capa 1
174
+ funcionó o no.
175
+
176
+ Una sola capa no basta: `.gitignore` no protege contra un bucket mal configurado
177
+ ni contra un desarrollador que copia logs a otro destino. El env flag por sí
178
+ solo no protege contra un commit accidental del log mismo.
179
+
180
+ ### Implementación canónica
181
+
182
+ ```python
183
+ # .gitignore (capa 1)
184
+ logs/
185
+ *.jsonl
186
+ *.log
187
+ data/local/
188
+ ```
189
+
190
+ ```python
191
+ # config.py (capa 2: runtime guard)
192
+ from pydantic import field_validator, Field
193
+ from pydantic_settings import BaseSettings
194
+
195
+ class Settings(BaseSettings):
196
+ environment: str = Field("development")
197
+ llm_prompt_audit_log_text: bool = Field(False)
198
+
199
+ @field_validator("llm_prompt_audit_log_text")
200
+ @classmethod
201
+ def _bloquear_en_produccion(cls, v: bool, info) -> bool:
202
+ ambiente = info.data.get("environment", "development")
203
+ if v and ambiente == "production":
204
+ raise ValueError(
205
+ "llm_prompt_audit_log_text=True está prohibido con "
206
+ "environment=production. Los logs contienen PII y no "
207
+ "pueden persistir fuera de dev/staging. "
208
+ "Para auditoría en prod, usar Presidio + redaction."
209
+ )
210
+ return v
211
+ ```
212
+
213
+ ```python
214
+ # En el servicio que loggea
215
+ from config import settings
216
+
217
+ def log_llm_prompt(prompt: str, user_id: str) -> None:
218
+ if not settings.llm_prompt_audit_log_text:
219
+ # Log sin el cuerpo del prompt: solo metadata
220
+ logger.info("llm_prompt_sent", extra={
221
+ "user_id_hash": _hash_estable(user_id),
222
+ "prompt_len": len(prompt),
223
+ "tokens_estimados": estimar_tokens(prompt),
224
+ })
225
+ return
226
+
227
+ # Este path es inalcanzable en production (validator lanza al cargar settings).
228
+ # Solo se alcanza en dev/staging con flag explícito.
229
+ logger.debug("llm_prompt_content", extra={
230
+ "user_id_hash": _hash_estable(user_id),
231
+ "prompt": prompt,
232
+ })
233
+ ```
234
+
235
+ ### Reglas
236
+
237
+ - **`.gitignore` es capa 1**: cubre el filesystem del repo. Verificar con `git check-ignore -v logs/foo.jsonl` que el path está cubierto.
238
+ - **El env flag es capa 2**: validar con test de integración que `environment=production + flag=True` lanza al cargar settings, **no** en runtime cuando se intenta loggear.
239
+ - **Nombres del flag explícitos**: `llm_prompt_audit_log_text`, `http_body_log_full`, `stacktrace_log_full_data` — el nombre debe dejar claro que habilita log de contenido sensible. Nombres genéricos como `debug_mode` no comunican el riesgo.
240
+ - **Tercera capa opcional pero recomendada**: en el logger central, aplicar filtro Presidio o regex para redactar patrones PII (email, RFC, teléfono, CURP) antes de escribir a disco. Esto convierte "si los 2 gates fallan, el daño es total" en "si los 2 gates fallan, el daño es parcial".
241
+ - **Test de capa 2 en CI**: test que crea `Settings(environment="production", llm_prompt_audit_log_text=True)` y verifica `ValidationError`. Sin este test, la capa 2 puede desactivarse silenciosamente en un refactor futuro.
242
+
243
+ ### Anti-patrón
244
+
245
+ ```python
246
+ # MAL — solo capa 1 (gitignore), sin hard-block en runtime
247
+ # Si un dev sube los logs a un bucket S3 o a Slack para debugging,
248
+ # la PII sale del perímetro sin alarma.
249
+
250
+ # MAL — solo capa 2, sin gitignore
251
+ # Si el flag se activó una vez y los logs quedaron en disco,
252
+ # un `git add .` en un pull request los filtra al repo público.
253
+
254
+ # MAL — log fuente de verdad para auditoría regulatoria
255
+ # Los logs JSONL no son un sistema de auditoría conforme. Para compliance
256
+ # (GDPR Art. 30, SOC 2 CC6.2), usar un audit trail dedicado con retención,
257
+ # integridad (merkle, firmas) y control de acceso separado del log operacional.
258
+ ```
259
+
260
+ ### Frameworks de seguridad
261
+
262
+ - OWASP Top 10 A02:2021 — Cryptographic Failures (incluye log exposure de PII).
263
+ - NIST CSF PR.DS-01 (data-at-rest protection), PR.DS-02 (data-in-transit).
264
+ - NIST AI RMF MANAGE-3.1 — AI system information, including sensitive data, is protected.
265
+ - GDPR Art. 5 principle of data minimization.
@@ -0,0 +1,356 @@
1
+ # IAM y Gestión de Secretos — Implementaciones Completas
2
+
3
+ ## ABAC — Control de Acceso Basado en Atributos
4
+
5
+ ABAC se usa cuando RBAC no es suficientemente granular.
6
+
7
+ ```python
8
+ # Ejemplo: un usuario OPERADOR sólo puede editar usuarios de su departamento
9
+ from dataclasses import dataclass
10
+ from typing import Any
11
+
12
+
13
+ @dataclass
14
+ class ContextoAutorizacion:
15
+ sujeto: dict # Atributos del usuario que hace la acción
16
+ recurso: dict # Atributos del recurso al que accede
17
+ accion: str # Acción que intenta realizar
18
+ entorno: dict # Hora, IP, etc.
19
+
20
+
21
+ def puede_editar_usuario(
22
+ usuario_solicitante: dict,
23
+ usuario_objetivo: dict,
24
+ ) -> bool:
25
+ """
26
+ Política ABAC: un OPERADOR sólo puede editar usuarios de su departamento.
27
+ Un ADMIN puede editar cualquier usuario en su organización.
28
+ Un SUPER puede editar cualquier usuario.
29
+ """
30
+ rol = usuario_solicitante.get("rol")
31
+
32
+ if rol == "SUPER":
33
+ return True
34
+
35
+ if rol == "ADMIN":
36
+ return (
37
+ usuario_solicitante.get("organizacion_id")
38
+ == usuario_objetivo.get("organizacion_id")
39
+ )
40
+
41
+ if rol == "OPERADOR":
42
+ return (
43
+ usuario_solicitante.get("departamento_id")
44
+ == usuario_objetivo.get("departamento_id")
45
+ and usuario_solicitante.get("organizacion_id")
46
+ == usuario_objetivo.get("organizacion_id")
47
+ )
48
+
49
+ return False
50
+
51
+
52
+ # En el endpoint — prevención de IDOR
53
+ @router.put("/usuarios/{usuario_id}")
54
+ async def actualizar_usuario(
55
+ usuario_id: str,
56
+ datos: ActualizarUsuarioSchema,
57
+ usuario_actual: Usuario = Depends(get_current_user),
58
+ db: AsyncSession = Depends(get_db),
59
+ ):
60
+ usuario_objetivo = await db.get(Usuario, usuario_id)
61
+ if not usuario_objetivo:
62
+ raise HTTPException(404, "Usuario no encontrado")
63
+
64
+ # ABAC — verificar autorización con atributos de ambos
65
+ if not puede_editar_usuario(
66
+ usuario_solicitante=usuario_actual.__dict__,
67
+ usuario_objetivo=usuario_objetivo.__dict__,
68
+ ):
69
+ raise HTTPException(403, "Sin permisos para editar este usuario")
70
+
71
+ # Continuar con la actualización...
72
+ ```
73
+
74
+ ---
75
+
76
+ ## HashiCorp Vault — Integración en Python
77
+
78
+ ```python
79
+ # vault_client.py
80
+ import hvac
81
+ import os
82
+ from functools import lru_cache
83
+ from typing import Any
84
+
85
+
86
+ @lru_cache(maxsize=1)
87
+ def obtener_cliente_vault() -> hvac.Client:
88
+ """Cliente Vault singleton — se autentica una vez por proceso."""
89
+ cliente = hvac.Client(url=os.environ["VAULT_ADDR"])
90
+
91
+ # Autenticación con rol de Kubernetes (en producción)
92
+ if os.environ.get("KUBERNETES_SERVICE_HOST"):
93
+ with open("/var/run/secrets/kubernetes.io/serviceaccount/token") as f:
94
+ jwt_token = f.read()
95
+
96
+ cliente.auth.kubernetes.login(
97
+ role=os.environ["VAULT_ROLE"],
98
+ jwt=jwt_token,
99
+ )
100
+ else:
101
+ # Autenticación con token (desarrollo local)
102
+ cliente.token = os.environ["VAULT_TOKEN"]
103
+
104
+ if not cliente.is_authenticated():
105
+ raise RuntimeError("No se pudo autenticar con Vault")
106
+
107
+ return cliente
108
+
109
+
110
+ def obtener_secreto(ruta: str, clave: str) -> str:
111
+ """
112
+ Lee un secreto de Vault KV v2.
113
+
114
+ Args:
115
+ ruta: Ruta en Vault, ej: "secret/data/produccion/base-de-datos"
116
+ clave: Clave específica dentro del secreto
117
+
118
+ Returns:
119
+ El valor del secreto como string.
120
+ """
121
+ cliente = obtener_cliente_vault()
122
+
123
+ try:
124
+ respuesta = cliente.secrets.kv.v2.read_secret_version(
125
+ path=ruta.replace("secret/data/", ""),
126
+ mount_point="secret",
127
+ )
128
+ valor = respuesta["data"]["data"].get(clave)
129
+
130
+ if valor is None:
131
+ raise KeyError(f"Clave {clave!r} no encontrada en {ruta!r}")
132
+
133
+ return valor
134
+
135
+ except hvac.exceptions.InvalidPath:
136
+ raise KeyError(f"Ruta de Vault no encontrada: {ruta!r}")
137
+
138
+
139
+ def obtener_credenciales_bd() -> dict[str, str]:
140
+ """Obtiene credenciales de base de datos con rotación automática vía Vault Dynamic Secrets."""
141
+ cliente = obtener_cliente_vault()
142
+
143
+ # Vault genera credenciales temporales que expiran automáticamente
144
+ creds = cliente.secrets.database.generate_credentials(
145
+ name="mi-aplicacion-rol",
146
+ mount_point="database",
147
+ )
148
+
149
+ return {
150
+ "usuario": creds["data"]["username"],
151
+ "contrasena": creds["data"]["password"],
152
+ "ttl": creds["lease_duration"],
153
+ }
154
+ ```
155
+
156
+ ---
157
+
158
+ ## AWS Secrets Manager — Integración con Caché
159
+
160
+ ```python
161
+ # aws_secrets.py
162
+ import boto3
163
+ import json
164
+ import time
165
+ from typing import Any
166
+ from dataclasses import dataclass, field
167
+
168
+
169
+ @dataclass
170
+ class SecretoEnCache:
171
+ valor: Any
172
+ expira_en: float # Unix timestamp
173
+
174
+
175
+ class ClienteSecretos:
176
+ """Cliente con caché local para reducir llamadas a AWS Secrets Manager."""
177
+
178
+ def __init__(self, region: str = "us-east-1", ttl_segundos: int = 300):
179
+ self._cliente = boto3.client("secretsmanager", region_name=region)
180
+ self._cache: dict[str, SecretoEnCache] = {}
181
+ self._ttl = ttl_segundos
182
+
183
+ def obtener(self, nombre_secreto: str) -> dict[str, Any]:
184
+ ahora = time.time()
185
+ entrada = self._cache.get(nombre_secreto)
186
+
187
+ if entrada and entrada.expira_en > ahora:
188
+ return entrada.valor
189
+
190
+ respuesta = self._cliente.get_secret_value(SecretId=nombre_secreto)
191
+
192
+ if "SecretString" in respuesta:
193
+ valor = json.loads(respuesta["SecretString"])
194
+ else:
195
+ valor = json.loads(respuesta["SecretBinary"].decode("utf-8"))
196
+
197
+ self._cache[nombre_secreto] = SecretoEnCache(
198
+ valor=valor,
199
+ expira_en=ahora + self._ttl,
200
+ )
201
+
202
+ return valor
203
+
204
+ def rotar(self, nombre_secreto: str) -> None:
205
+ """Fuerza rotación inmediata y limpia el caché."""
206
+ self._cliente.rotate_secret(SecretId=nombre_secreto)
207
+ self._cache.pop(nombre_secreto, None)
208
+
209
+
210
+ # Uso en la aplicación
211
+ _secretos = ClienteSecretos(region="us-east-1")
212
+
213
+
214
+ def get_db_url() -> str:
215
+ creds = _secretos.obtener("produccion/bd-principal")
216
+ return (
217
+ f"postgresql+asyncpg://{creds['usuario']}:{creds['contrasena']}"
218
+ f"@{creds['host']}:{creds['puerto']}/{creds['nombre_bd']}"
219
+ )
220
+ ```
221
+
222
+ ---
223
+
224
+ ## Gestión de API Keys
225
+
226
+ ```python
227
+ # api_keys.py
228
+ import secrets
229
+ import hashlib
230
+ from datetime import datetime, timedelta, timezone
231
+
232
+
233
+ def generar_api_key() -> tuple[str, str]:
234
+ """
235
+ Genera una API key y su hash para almacenamiento.
236
+ La clave en texto plano se muestra UNA SOLA VEZ al usuario.
237
+ Solo el hash se almacena en la base de datos.
238
+ """
239
+ clave = f"sk_{secrets.token_urlsafe(32)}"
240
+ hash_clave = hashlib.sha256(clave.encode()).hexdigest()
241
+ return clave, hash_clave
242
+
243
+
244
+ def verificar_api_key(clave_recibida: str, hash_almacenado: str) -> bool:
245
+ """Verifica una API key en tiempo constante para prevenir timing attacks."""
246
+ hash_recibido = hashlib.sha256(clave_recibida.encode()).hexdigest()
247
+ return secrets.compare_digest(hash_recibido, hash_almacenado)
248
+
249
+
250
+ # Modelo de API Key con scopes y expiración
251
+ from sqlalchemy import String, DateTime, ARRAY
252
+ from sqlalchemy.orm import Mapped, mapped_column
253
+
254
+
255
+ class APIKey(Base):
256
+ __tablename__ = "api_keys"
257
+
258
+ id: Mapped[str] = mapped_column(String, primary_key=True)
259
+ nombre: Mapped[str] = mapped_column(String(100))
260
+ hash_clave: Mapped[str] = mapped_column(String(64), unique=True, index=True)
261
+ scopes: Mapped[list[str]] = mapped_column(ARRAY(String))
262
+ propietario_id: Mapped[str] = mapped_column(String(255))
263
+ expira_en: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
264
+ ultimo_uso: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
265
+ activa: Mapped[bool] = mapped_column(default=True)
266
+
267
+ def esta_vigente(self) -> bool:
268
+ if not self.activa:
269
+ return False
270
+ if self.expira_en and self.expira_en < datetime.now(timezone.utc):
271
+ return False
272
+ return True
273
+ ```
274
+
275
+ ---
276
+
277
+ ## Rotación de Secretos — Estrategia
278
+
279
+ ```yaml
280
+ # Política de rotación por tipo de secreto
281
+ rotacion:
282
+ credenciales_bd:
283
+ frecuencia: "cada 7 días"
284
+ estrategia: "doble escritura"
285
+ pasos:
286
+ 1: "Crear nuevo usuario de BD"
287
+ 2: "Actualizar secreto en Vault/AWS SM"
288
+ 3: "Desplegar nueva versión de la app"
289
+ 4: "Verificar que la nueva versión funciona"
290
+ 5: "Revocar credenciales antiguas"
291
+
292
+ jwt_secret:
293
+ frecuencia: "cada 30 días"
294
+ estrategia: "período de gracia de 24h"
295
+ pasos:
296
+ 1: "Generar nuevo secret"
297
+ 2: "Configurar validación de AMBOS secrets (nuevo y viejo) durante 24h"
298
+ 3: "Después de 24h, eliminar el viejo"
299
+
300
+ api_keys_externas:
301
+ frecuencia: "cada 90 días"
302
+ estrategia: "reemplazo directo con downtime cero"
303
+ notas: "Las APIs externas dan período de transición de 24-72h"
304
+
305
+ certificados_tls:
306
+ frecuencia: "cada 90 días (automático con cert-manager/Let's Encrypt)"
307
+ alerta_anticipacion: "30 días antes de expiración"
308
+ ```
309
+
310
+ ---
311
+
312
+ ## Configuración de Cuentas de Servicio — Kubernetes
313
+
314
+ ```yaml
315
+ # k8s/service-account.yaml
316
+ apiVersion: v1
317
+ kind: ServiceAccount
318
+ metadata:
319
+ name: api-backend
320
+ namespace: produccion
321
+ annotations:
322
+ eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/api-backend-role
323
+
324
+ ---
325
+ apiVersion: rbac.authorization.k8s.io/v1
326
+ kind: Role
327
+ metadata:
328
+ name: api-backend-role
329
+ namespace: produccion
330
+ rules:
331
+ # Solo leer secrets propios — NO acceso a todos los secrets
332
+ - apiGroups: [""]
333
+ resources: ["secrets"]
334
+ resourceNames: ["api-backend-secrets"]
335
+ verbs: ["get"]
336
+ # Solo leer configmaps propios
337
+ - apiGroups: [""]
338
+ resources: ["configmaps"]
339
+ resourceNames: ["api-backend-config"]
340
+ verbs: ["get", "watch"]
341
+
342
+ ---
343
+ apiVersion: rbac.authorization.k8s.io/v1
344
+ kind: RoleBinding
345
+ metadata:
346
+ name: api-backend-binding
347
+ namespace: produccion
348
+ subjects:
349
+ - kind: ServiceAccount
350
+ name: api-backend
351
+ namespace: produccion
352
+ roleRef:
353
+ kind: Role
354
+ name: api-backend-role
355
+ apiGroup: rbac.authorization.k8s.io
356
+ ```