@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,390 @@
1
+ # Manejo de Errores Stripe y Estrategias de Reintento
2
+
3
+ Stripe clasifica los errores en categorías con semántica distinta. Manejarlos
4
+ correctamente determina si el usuario ve un mensaje útil, si el sistema se
5
+ recupera solo, o si un pago legítimo se pierde por un error transitorio.
6
+
7
+ ---
8
+
9
+ ## Tipos de errores Stripe
10
+
11
+ ### Jerarquía de excepciones del SDK Python
12
+
13
+ ```
14
+ stripe.error.StripeError # Base — todos los errores Stripe
15
+ ├── stripe.error.CardError # Tarjeta declinada por el banco emisor
16
+ ├── stripe.error.RateLimitError # Demasiadas peticiones (429)
17
+ ├── stripe.error.InvalidRequestError # Parámetros inválidos (400)
18
+ ├── stripe.error.AuthenticationError # API key inválida (401)
19
+ ├── stripe.error.PermissionError # Sin permisos para la operación (403)
20
+ ├── stripe.error.APIConnectionError # Error de red — Stripe no respondió
21
+ ├── stripe.error.IdempotencyError # Idempotency key reutilizada incorrectamente
22
+ └── stripe.error.APIError # Error interno de Stripe (5xx)
23
+ ```
24
+
25
+ ### Atributos clave en CardError
26
+
27
+ ```python
28
+ try:
29
+ stripe.PaymentIntent.create(...)
30
+ except stripe.error.CardError as e:
31
+ error = e.error
32
+ # error.code: 'card_declined', 'insufficient_funds', 'expired_card', etc.
33
+ # error.decline_code: sub-código del banco emisor
34
+ # error.message: mensaje técnico de Stripe (inglés)
35
+ # error.param: parámetro que causó el error (si aplica)
36
+ print(error.code, error.decline_code)
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Clasificación por tipo y estrategia de manejo
42
+
43
+ | Error | Tipo | ¿Reintentar? | Acción recomendada |
44
+ |-------|------|-------------|-------------------|
45
+ | `card_declined` | CardError | No | Pedir nueva tarjeta al usuario |
46
+ | `insufficient_funds` | CardError | No | Informar fondos insuficientes |
47
+ | `expired_card` | CardError | No | Pedir nueva tarjeta |
48
+ | `incorrect_cvc` | CardError | No (max 3x) | Pedir CVV de nuevo |
49
+ | `authentication_required` | CardError | Sí (con 3DS) | Redirigir a 3D Secure |
50
+ | `rate_limit_error` | RateLimitError | Sí (backoff) | Retry con espera exponencial |
51
+ | `api_connection_error` | APIConnectionError | Sí (backoff) | Retry — error de red |
52
+ | `api_error` (5xx) | APIError | Sí (backoff) | Retry — error interno Stripe |
53
+ | `idempotency_error` | IdempotencyError | No | Revisar la key — bug en código |
54
+ | `invalid_request_error` | InvalidRequestError | No | Bug en la llamada — no reintentar |
55
+
56
+ ---
57
+
58
+ ## Retry con backoff exponencial para errores transitorios
59
+
60
+ ```python
61
+ import asyncio
62
+ import logging
63
+ import stripe
64
+ from typing import TypeVar, Callable, Awaitable
65
+
66
+ logger = logging.getLogger(__name__)
67
+ T = TypeVar("T")
68
+
69
+ # Errores que justifican reintento automático
70
+ ERRORES_REINTENTABLES = (
71
+ stripe.error.RateLimitError,
72
+ stripe.error.APIConnectionError,
73
+ stripe.error.APIError,
74
+ )
75
+
76
+
77
+ async def stripe_con_retry(
78
+ operacion: Callable[[], T | Awaitable[T]],
79
+ max_reintentos: int = 3,
80
+ base_delay_segundos: float = 1.0,
81
+ operacion_nombre: str = "stripe_call",
82
+ ) -> T:
83
+ """
84
+ Ejecuta una operación de Stripe con retry exponencial.
85
+ Solo reintenta errores transitorios — nunca CardError ni errores de validación.
86
+ """
87
+ ultimo_error: Exception | None = None
88
+
89
+ for intento in range(max_reintentos + 1):
90
+ try:
91
+ resultado = operacion()
92
+ if asyncio.iscoroutine(resultado):
93
+ return await resultado
94
+ return resultado
95
+
96
+ except ERRORES_REINTENTABLES as exc:
97
+ ultimo_error = exc
98
+ if intento == max_reintentos:
99
+ logger.error(
100
+ "Operación Stripe agotó reintentos",
101
+ operacion=operacion_nombre,
102
+ intentos=intento + 1,
103
+ error=str(exc),
104
+ )
105
+ raise
106
+
107
+ # Backoff exponencial con jitter: 1s, 2s, 4s + ruido aleatorio
108
+ import random
109
+ delay = (base_delay_segundos * (2 ** intento)) + random.uniform(0, 0.5)
110
+ logger.warning(
111
+ "Error transitorio Stripe — reintentando",
112
+ operacion=operacion_nombre,
113
+ intento=intento + 1,
114
+ delay_segundos=round(delay, 2),
115
+ error_tipo=type(exc).__name__,
116
+ )
117
+ await asyncio.sleep(delay)
118
+
119
+ except (
120
+ stripe.error.CardError,
121
+ stripe.error.InvalidRequestError,
122
+ stripe.error.AuthenticationError,
123
+ stripe.error.IdempotencyError,
124
+ ):
125
+ # Errores no reintentables — fallar inmediatamente
126
+ raise
127
+
128
+ raise RuntimeError("No debería llegar aquí") from ultimo_error
129
+
130
+
131
+ # Uso
132
+ async def crear_intent_con_retry(orden: Orden) -> stripe.PaymentIntent:
133
+ return await stripe_con_retry(
134
+ lambda: stripe.PaymentIntent.create(
135
+ amount=int(orden.total * 100),
136
+ currency="mxn",
137
+ idempotency_key=f"pi_{orden.id}",
138
+ ),
139
+ operacion_nombre=f"crear_payment_intent_{orden.id}",
140
+ )
141
+ ```
142
+
143
+ ---
144
+
145
+ ## Manejo de declinación de tarjeta: mensajes user-friendly
146
+
147
+ Los mensajes técnicos de Stripe están en inglés y son inapropiados para mostrar
148
+ al usuario. Mapear a mensajes en español claros y útiles:
149
+
150
+ ```python
151
+ # services/mensajes_pago.py
152
+
153
+ MENSAJES_DECLINACION: dict[str | None, str] = {
154
+ # Códigos de CardError.code
155
+ "card_declined": "Tu tarjeta fue declinada. Verifica que los datos sean correctos o intenta con otra tarjeta.",
156
+ "insufficient_funds": "Tu tarjeta no tiene fondos suficientes para esta compra.",
157
+ "expired_card": "Tu tarjeta ha expirado. Por favor usa una tarjeta vigente.",
158
+ "incorrect_cvc": "El código de seguridad (CVV) es incorrecto. Revísalo e intenta de nuevo.",
159
+ "incorrect_number": "El número de tarjeta es incorrecto.",
160
+ "invalid_expiry_month": "El mes de vencimiento no es válido.",
161
+ "invalid_expiry_year": "El año de vencimiento no es válido.",
162
+ "card_velocity_exceeded": "Has excedido el límite de intentos. Intenta más tarde o usa otra tarjeta.",
163
+ "do_not_honor": "Tu banco no autorizó el cargo. Contacta a tu banco para más información.",
164
+ "fraudulent": "Esta transacción fue bloqueada por seguridad. Contacta a tu banco.",
165
+ "authentication_required": "Tu banco requiere autenticación adicional. Completa el proceso de verificación.",
166
+ # Fallback para códigos desconocidos
167
+ None: "No pudimos procesar tu pago. Verifica los datos de tu tarjeta o intenta con otra.",
168
+ }
169
+
170
+ # Códigos del banco emisor (decline_code) — más específicos
171
+ MENSAJES_DECLINE_CODE: dict[str, str] = {
172
+ "insufficient_funds": "Fondos insuficientes en tu tarjeta.",
173
+ "lost_card": "Esta tarjeta fue reportada como perdida. Contacta a tu banco.",
174
+ "stolen_card": "Esta tarjeta fue reportada como robada. Contacta a tu banco.",
175
+ "generic_decline": "Tu banco no autorizó el pago. Intenta con otra tarjeta o contacta a tu banco.",
176
+ "do_not_honor": "Tu banco no autorizó el cargo. Contacta a tu banco directamente.",
177
+ "card_not_supported": "Tu tarjeta no está habilitada para pagos en línea.",
178
+ "currency_not_supported": "Tu tarjeta no acepta pagos en esta moneda.",
179
+ }
180
+
181
+
182
+ def obtener_mensaje_declinacion(error: stripe.error.CardError) -> str:
183
+ """Retorna un mensaje en español apropiado para mostrar al usuario."""
184
+ err = error.error
185
+
186
+ # Intentar con decline_code primero (más específico)
187
+ if err.decline_code and err.decline_code in MENSAJES_DECLINE_CODE:
188
+ return MENSAJES_DECLINE_CODE[err.decline_code]
189
+
190
+ # Luego con code
191
+ return MENSAJES_DECLINACION.get(
192
+ err.code,
193
+ MENSAJES_DECLINACION[None],
194
+ )
195
+ ```
196
+
197
+ ---
198
+
199
+ ## Dunning management: reintentos automáticos en suscripciones
200
+
201
+ Cuando el cobro de una suscripción falla, Stripe implementa "dunning": reintentos
202
+ automáticos según el schedule configurado en el dashboard. El sistema maneja esto
203
+ de forma transparente, pero la app debe reaccionar a los eventos:
204
+
205
+ ```python
206
+ # Configuración recomendada en el dashboard de Stripe (Smart Retries):
207
+ # - Reintento 1: 3 días después del fallo
208
+ # - Reintento 2: 5 días después del primer reintento
209
+ # - Reintento 3: 7 días después del segundo reintento
210
+ # - Después del último reintento: cancelar suscripción o marcar como unpaid
211
+
212
+ # La app debe manejar estos eventos para degradar o restaurar acceso:
213
+
214
+ async def manejar_invoice_payment_failed(invoice: dict) -> None:
215
+ """
216
+ Se llama cuando Stripe no pudo cobrar una factura.
217
+ Estado de suscripción: active → past_due → unpaid → canceled
218
+ """
219
+ from app.models.subscripciones import Subscripcion
220
+ from sqlalchemy import select, update
221
+
222
+ stripe_subscription_id = invoice.get("subscription")
223
+ if not stripe_subscription_id:
224
+ return
225
+
226
+ # Obtener el número de intento para decidir la acción
227
+ attempt_count = invoice.get("attempt_count", 1)
228
+
229
+ async with AsyncSessionLocal() as db:
230
+ sub = await db.scalar(
231
+ select(Subscripcion).where(
232
+ Subscripcion.stripe_subscription_id == stripe_subscription_id
233
+ )
234
+ )
235
+ if sub is None:
236
+ return
237
+
238
+ if attempt_count == 1:
239
+ # Primer fallo — notificar al usuario, no restringir aún
240
+ await enviar_notificacion_pago_fallido(sub.usuario_id, intento=1)
241
+ elif attempt_count == 2:
242
+ # Segundo fallo — advertencia urgente
243
+ await enviar_notificacion_pago_fallido(sub.usuario_id, intento=2)
244
+ else:
245
+ # Tercer fallo o más — restringir acceso parcialmente
246
+ await db.execute(
247
+ update(Subscripcion)
248
+ .where(Subscripcion.id == sub.id)
249
+ .values(acceso_restringido=True)
250
+ )
251
+ await enviar_notificacion_suspension_inminente(sub.usuario_id)
252
+ await db.commit()
253
+
254
+
255
+ async def manejar_subscripcion_cancelada_por_no_pago(sub: dict) -> None:
256
+ """
257
+ Se llama cuando Stripe cancela la suscripción por reintentos agotados.
258
+ Revocar acceso completamente.
259
+ """
260
+ async with AsyncSessionLocal() as db:
261
+ from sqlalchemy import update
262
+ from app.models.subscripciones import Subscripcion
263
+
264
+ await db.execute(
265
+ update(Subscripcion)
266
+ .where(Subscripcion.stripe_subscription_id == sub["id"])
267
+ .values(estado="cancelada", acceso_restringido=True)
268
+ )
269
+ await db.commit()
270
+ ```
271
+
272
+ ---
273
+
274
+ ## Dispute handling: evidencia requerida por tipo de disputa
275
+
276
+ Una disputa (chargeback) ocurre cuando el tarjetahabiente impugna un cargo
277
+ ante su banco. Stripe genera el evento `charge.dispute.created`.
278
+
279
+ ```python
280
+ async def manejar_disputa(disputa: stripe.Dispute) -> None:
281
+ """
282
+ Responde automáticamente a disputas con evidencia disponible.
283
+ El plazo para responder es típicamente 7-21 días según el banco emisor.
284
+ """
285
+ from app.models.ordenes import Orden
286
+
287
+ # Obtener la orden relacionada
288
+ payment_intent_id = disputa.payment_intent
289
+ orden = await Orden.objects.aget(
290
+ stripe_payment_intent_id=payment_intent_id
291
+ )
292
+
293
+ # Tipos de disputa y evidencia requerida
294
+ razon = disputa.reason
295
+ evidencia: dict = {}
296
+
297
+ if razon in ("fraudulent", "unrecognized"):
298
+ # El cliente dice no reconocer el cargo
299
+ evidencia = {
300
+ "billing_address": orden.direccion_facturacion,
301
+ "customer_email_address": orden.usuario.email,
302
+ "customer_ip_address": orden.ip_cliente,
303
+ "receipt": orden.url_recibo,
304
+ "shipping_documentation": orden.url_guia_envio,
305
+ "uncategorized_text": (
306
+ f"El cliente {orden.usuario.email} realizó la compra el "
307
+ f"{orden.creado_en.strftime('%d/%m/%Y')} desde la IP "
308
+ f"{orden.ip_cliente}. Se enviaron notificaciones de confirmación "
309
+ f"a su correo registrado."
310
+ ),
311
+ }
312
+
313
+ elif razon == "product_not_received":
314
+ # El cliente dice no haber recibido el producto
315
+ evidencia = {
316
+ "shipping_documentation": orden.url_guia_envio,
317
+ "shipping_tracking_number": orden.numero_guia,
318
+ "shipping_carrier": orden.paqueteria,
319
+ "shipping_date": orden.fecha_envio.strftime("%Y-%m-%d"),
320
+ "uncategorized_text": (
321
+ f"El pedido fue enviado el {orden.fecha_envio.strftime('%d/%m/%Y')} "
322
+ f"por {orden.paqueteria} con guía {orden.numero_guia}. "
323
+ f"Estado de entrega: {orden.estado_entrega}."
324
+ ),
325
+ }
326
+
327
+ elif razon == "duplicate":
328
+ # El cliente dice que el cargo está duplicado
329
+ evidencia = {
330
+ "duplicate_charge_id": disputa.charge,
331
+ "duplicate_charge_explanation": (
332
+ "Este cargo corresponde a una única transacción. "
333
+ f"El ID de orden es {orden.numero}."
334
+ ),
335
+ "receipt": orden.url_recibo,
336
+ }
337
+
338
+ if evidencia:
339
+ stripe.Dispute.modify(
340
+ disputa.id,
341
+ evidence=evidencia,
342
+ submit=True, # Enviar inmediatamente a Stripe para revisión
343
+ )
344
+ logger.info(
345
+ "Evidencia de disputa enviada",
346
+ disputa_id=disputa.id,
347
+ razon=razon,
348
+ orden_id=str(orden.id),
349
+ )
350
+ ```
351
+
352
+ ### Tipos de disputa y evidencia óptima
353
+
354
+ | Razón de disputa | Evidencia más efectiva |
355
+ |-----------------|----------------------|
356
+ | `fraudulent` | IP del cliente, email de confirmación, historial de compras |
357
+ | `unrecognized` | Email de confirmación, descripción del producto, IP |
358
+ | `product_not_received` | Guía de envío, número de rastreo, fecha de entrega |
359
+ | `product_unacceptable` | Política de devoluciones, comunicación con el cliente |
360
+ | `duplicate` | Explicación del cargo, recibo original |
361
+ | `subscription_canceled` | Fecha de cancelación, términos de servicio |
362
+ | `credit_not_processed` | Documentación del reembolso ya procesado |
363
+
364
+ ---
365
+
366
+ ## Alertas y monitoreo de salud de pagos
367
+
368
+ ```python
369
+ # Métricas clave a monitorear (enviar a tu sistema de alertas)
370
+
371
+ ALERTAS_PAGOS = {
372
+ # Tasa de declinación > 10% en 1 hora → posible fraude o problema técnico
373
+ "tasa_declinacion_alta": {
374
+ "umbral": 0.10,
375
+ "ventana_minutos": 60,
376
+ "severidad": "alta",
377
+ },
378
+ # Más de 3 disputas en 24 horas → revisar calidad del producto/servicio
379
+ "disputas_frecuentes": {
380
+ "umbral": 3,
381
+ "ventana_horas": 24,
382
+ "severidad": "media",
383
+ },
384
+ # Webhook sin procesar por más de 5 minutos → posible problema en el endpoint
385
+ "webhook_delayed": {
386
+ "umbral_minutos": 5,
387
+ "severidad": "alta",
388
+ },
389
+ }
390
+ ```
@@ -0,0 +1,290 @@
1
+ # Stripe Connect — Marketplaces y Plataformas
2
+
3
+ Stripe Connect permite que una plataforma facilite pagos entre compradores
4
+ y vendedores (o prestadores de servicio), reteniendo una comisión y pagando
5
+ a los vendedores automáticamente. Es el sistema detrás de marketplaces como
6
+ Airbnb, Etsy o plataformas de freelancers.
7
+
8
+ ---
9
+
10
+ ## Modelo de negocio: plataforma → vendedor → cliente
11
+
12
+ ```
13
+ Cliente
14
+ |
15
+ | paga $1,000 MXN
16
+ v
17
+ Plataforma (cuenta Stripe principal)
18
+ |
19
+ | transfiere $900 MXN al vendedor
20
+ | retiene $100 MXN como comisión
21
+ v
22
+ Vendedor (cuenta Stripe Connect — "connected account")
23
+ ```
24
+
25
+ La plataforma es responsable ante Stripe de los pagos. Los vendedores reciben
26
+ payouts directamente en su cuenta bancaria según el schedule configurado.
27
+
28
+ ---
29
+
30
+ ## Tipos de cargos en Connect
31
+
32
+ ### 1. Destination Charges (recomendado para la mayoría de casos)
33
+
34
+ El cargo se crea en la cuenta de la **plataforma** y se transfiere al vendedor.
35
+ La plataforma es responsable de disputas y reembolsos.
36
+
37
+ ```python
38
+ import stripe
39
+ from app.core.config import settings
40
+
41
+ stripe.api_key = settings.STRIPE_SECRET_KEY
42
+
43
+
44
+ async def crear_cobro_marketplace(
45
+ monto_total_centavos: int,
46
+ comision_plataforma_centavos: int,
47
+ stripe_account_id_vendedor: str,
48
+ orden_id: str,
49
+ ) -> stripe.PaymentIntent:
50
+ """
51
+ Crea un Destination Charge.
52
+ El cliente paga monto_total; el vendedor recibe (monto_total - comision).
53
+ """
54
+ return stripe.PaymentIntent.create(
55
+ amount=monto_total_centavos,
56
+ currency="mxn",
57
+ # La comisión que retiene la plataforma
58
+ application_fee_amount=comision_plataforma_centavos,
59
+ # La cuenta Connect del vendedor recibe el resto
60
+ transfer_data={
61
+ "destination": stripe_account_id_vendedor,
62
+ },
63
+ metadata={"orden_id": orden_id},
64
+ idempotency_key=f"pi_marketplace_{orden_id}",
65
+ )
66
+ ```
67
+
68
+ ### 2. Direct Charges (para mayor autonomía del vendedor)
69
+
70
+ El cargo se crea directamente en la cuenta del **vendedor**. La plataforma
71
+ toma su comisión vía `application_fee_amount`. El vendedor maneja disputas.
72
+ Requiere que el cliente conozca la marca del vendedor.
73
+
74
+ ```python
75
+ async def crear_cobro_directo(
76
+ monto_centavos: int,
77
+ comision_centavos: int,
78
+ stripe_account_id_vendedor: str,
79
+ orden_id: str,
80
+ ) -> stripe.PaymentIntent:
81
+ """Cargo directo en la cuenta del vendedor."""
82
+ return stripe.PaymentIntent.create(
83
+ amount=monto_centavos,
84
+ currency="mxn",
85
+ application_fee_amount=comision_centavos,
86
+ metadata={"orden_id": orden_id},
87
+ idempotency_key=f"pi_direct_{orden_id}",
88
+ stripe_account=stripe_account_id_vendedor, # Clave: ejecutar en cuenta del vendedor
89
+ )
90
+ ```
91
+
92
+ ### 3. Separate Charges and Transfers (control máximo)
93
+
94
+ Cobra al cliente en la cuenta de la plataforma y crea transferencias
95
+ independientes a uno o varios vendedores. Útil cuando un pedido tiene
96
+ productos de múltiples vendedores.
97
+
98
+ ```python
99
+ async def distribuir_pago_multi_vendedor(
100
+ payment_intent_id: str,
101
+ distribuciones: list[dict], # [{"account": "acct_xxx", "amount": 500}]
102
+ ) -> list[stripe.Transfer]:
103
+ """
104
+ Transfiere partes del pago a múltiples vendedores.
105
+ Llamar DESPUÉS de que el PaymentIntent sea exitoso.
106
+ """
107
+ transferencias = []
108
+ for dist in distribuciones:
109
+ transferencia = stripe.Transfer.create(
110
+ amount=dist["amount"],
111
+ currency="mxn",
112
+ destination=dist["account"],
113
+ source_transaction=payment_intent_id,
114
+ idempotency_key=f"transfer_{payment_intent_id}_{dist['account']}",
115
+ )
116
+ transferencias.append(transferencia)
117
+ return transferencias
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Onboarding de vendedores: AccountLink para KYC
123
+
124
+ Stripe requiere verificar la identidad de los vendedores (KYC — Know Your Customer)
125
+ antes de permitirles recibir pagos. Este proceso se realiza vía AccountLink.
126
+
127
+ ### Paso 1: Crear la cuenta Connect del vendedor
128
+
129
+ ```python
130
+ async def crear_cuenta_vendedor(
131
+ email: str,
132
+ usuario_id: str,
133
+ ) -> stripe.Account:
134
+ """
135
+ Crea una cuenta Connect de tipo 'express' (recomendado).
136
+ - express: Stripe maneja el onboarding UI (dashboard simplificado para el vendedor)
137
+ - standard: el vendedor tiene acceso completo al dashboard de Stripe
138
+ - custom: la plataforma controla toda la UI (requiere más trabajo y responsabilidad)
139
+ """
140
+ cuenta = stripe.Account.create(
141
+ type="express",
142
+ email=email,
143
+ country="MX",
144
+ capabilities={
145
+ "card_payments": {"requested": True},
146
+ "transfers": {"requested": True},
147
+ },
148
+ business_type="individual",
149
+ metadata={"usuario_id": usuario_id},
150
+ )
151
+ # Guardar cuenta.id como stripe_connect_account_id en la BD del vendedor
152
+ return cuenta
153
+
154
+
155
+ async def generar_link_onboarding(
156
+ stripe_account_id: str,
157
+ usuario_id: str,
158
+ ) -> str:
159
+ """
160
+ Genera un AccountLink para que el vendedor complete el KYC.
161
+ El link expira en ~10 minutos — generar justo antes de redirigir.
162
+ """
163
+ link = stripe.AccountLink.create(
164
+ account=stripe_account_id,
165
+ refresh_url=f"{settings.BASE_URL}/vendedores/onboarding/reiniciar",
166
+ return_url=f"{settings.BASE_URL}/vendedores/onboarding/completado",
167
+ type="account_onboarding",
168
+ )
169
+ return link.url
170
+
171
+
172
+ async def verificar_onboarding_completo(stripe_account_id: str) -> bool:
173
+ """Verifica si el vendedor completó el KYC y puede recibir pagos."""
174
+ cuenta = stripe.Account.retrieve(stripe_account_id)
175
+ return (
176
+ cuenta.details_submitted
177
+ and cuenta.charges_enabled
178
+ and cuenta.payouts_enabled
179
+ )
180
+ ```
181
+
182
+ ### Flujo de onboarding completo
183
+
184
+ ```
185
+ 1. Vendedor hace clic en "Conectar cuenta de pagos"
186
+ 2. Backend llama crear_cuenta_vendedor() → guarda stripe_connect_account_id
187
+ 3. Backend llama generar_link_onboarding() → redirige al vendedor a Stripe
188
+ 4. Vendedor completa KYC en Stripe (CURP, datos bancarios, etc.)
189
+ 5. Stripe redirige a return_url
190
+ 6. Backend llama verificar_onboarding_completo() para confirmar
191
+ 7. Stripe envía webhook account.updated cuando cambia el estado
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Splits de pago: application_fee_amount
197
+
198
+ La comisión de la plataforma se especifica en `application_fee_amount` (centavos).
199
+ Esta comisión se retiene automáticamente antes de transferir al vendedor.
200
+
201
+ ```python
202
+ # Ejemplo: orden de $1,000 MXN con 10% de comisión de plataforma
203
+ monto_total = 100_000 # $1,000.00 MXN en centavos
204
+ comision = 10_000 # $100.00 MXN (10%)
205
+ # El vendedor recibe: $900.00 MXN
206
+
207
+ # Cálculo dinámico de comisión
208
+ def calcular_comision(monto_centavos: int, porcentaje: float) -> int:
209
+ """Retorna la comisión en centavos, redondeando hacia arriba."""
210
+ import math
211
+ return math.ceil(monto_centavos * porcentaje / 100)
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Payout schedule para vendedores
217
+
218
+ Por defecto, Stripe realiza payouts automáticos a las cuentas bancarias de
219
+ los vendedores. Se puede configurar el schedule por cuenta:
220
+
221
+ ```python
222
+ async def configurar_payout_schedule(
223
+ stripe_account_id: str,
224
+ intervalo: str = "weekly", # "daily" | "weekly" | "monthly"
225
+ dia_semana: str = "friday", # Para weekly
226
+ ) -> stripe.Account:
227
+ """
228
+ Configura cuándo recibe payouts el vendedor.
229
+ - daily: cada día hábil (requiere cuenta activa por ≥ 7 días)
230
+ - weekly: el día especificado de la semana
231
+ - monthly: el día especificado del mes (1-31)
232
+ """
233
+ return stripe.Account.modify(
234
+ stripe_account_id,
235
+ settings={
236
+ "payouts": {
237
+ "schedule": {
238
+ "interval": intervalo,
239
+ "weekly_anchor": dia_semana,
240
+ }
241
+ }
242
+ },
243
+ stripe_account=stripe_account_id,
244
+ )
245
+ ```
246
+
247
+ ---
248
+
249
+ ## Webhooks críticos para Connect
250
+
251
+ Además de los webhooks estándar, Connect genera eventos para cuentas conectadas:
252
+
253
+ ```python
254
+ # El header stripe-signature sigue siendo obligatorio verificar
255
+ # Los eventos de cuentas conectadas incluyen account.updated
256
+
257
+ match evento.type:
258
+ case "account.updated":
259
+ # Verificar si el vendedor completó onboarding
260
+ cuenta = evento.data.object
261
+ await actualizar_estado_vendedor(cuenta.id, cuenta.charges_enabled)
262
+ case "account.application.deauthorized":
263
+ # El vendedor desconectó la plataforma — revocar acceso
264
+ await revocar_vendedor(evento.data.object.id)
265
+ case "transfer.created":
266
+ # Transferencia enviada al vendedor
267
+ await registrar_transferencia(evento.data.object)
268
+ case "payout.paid":
269
+ # El vendedor recibió el dinero en su banco
270
+ await marcar_payout_pagado(evento.data.object)
271
+ case "payout.failed":
272
+ # El payout falló (cuenta bancaria inválida, etc.)
273
+ await notificar_payout_fallido(evento.data.object)
274
+ ```
275
+
276
+ ---
277
+
278
+ ## MUST DO / MUST NOT DO en Connect
279
+
280
+ **MUST DO:**
281
+ - Guardar `stripe_connect_account_id` en la BD del vendedor desde el momento de creación.
282
+ - Verificar `charges_enabled` Y `payouts_enabled` antes de permitir transacciones.
283
+ - Manejar `account.updated` para actualizar el estado de onboarding en tiempo real.
284
+ - Escalar `application_fee_amount` según la lógica de negocio de cada transacción.
285
+
286
+ **MUST NOT DO:**
287
+ - NUNCA crear un transfer sin `source_transaction` — vincula la transferencia al cobro.
288
+ - NUNCA hacer payouts manuales cuando el schedule automático es suficiente.
289
+ - NUNCA asumir que el return_url significa que el onboarding está completo — verificar con la API.
290
+ - NUNCA compartir el `stripe_account_id` de un vendedor con otros vendedores.