@saulwade/swl-ses 2.4.3 → 2.5.2

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 (200) hide show
  1. package/CLAUDE.md +194 -241
  2. package/README.md +600 -597
  3. package/agentes/_intent-spec.md +73 -73
  4. package/agentes/_propose-step.md +90 -90
  5. package/agentes/abogado-diablo-swl.md +145 -0
  6. package/agentes/accesibilidad-wcag-swl.md +690 -690
  7. package/agentes/arquitecto-swl.md +267 -267
  8. package/agentes/auto-evolucion-swl.md +908 -908
  9. package/agentes/backend-api-swl.md +1 -1
  10. package/agentes/backend-csharp-swl.md +420 -420
  11. package/agentes/backend-go-swl.md +390 -390
  12. package/agentes/backend-java-swl.md +281 -281
  13. package/agentes/backend-node-swl.md +1 -1
  14. package/agentes/backend-python-swl.md +1 -1
  15. package/agentes/backend-rust-swl.md +364 -364
  16. package/agentes/backend-workers-swl.md +482 -482
  17. package/agentes/cloud-infra-swl.md +509 -509
  18. package/agentes/consolidador-swl.md +541 -541
  19. package/agentes/datos-swl.md +1 -1
  20. package/agentes/depurador-swl.md +352 -352
  21. package/agentes/devops-ci-swl.md +400 -400
  22. package/agentes/disenador-ui-swl.md +569 -569
  23. package/agentes/documentador-swl.md +345 -345
  24. package/agentes/frontend-angular-swl.md +621 -621
  25. package/agentes/frontend-css-swl.md +716 -716
  26. package/agentes/frontend-react-swl.md +692 -692
  27. package/agentes/frontend-swl.md +496 -496
  28. package/agentes/frontend-tailwind-swl.md +826 -826
  29. package/agentes/gh-fix-ci-swl.md +6 -1
  30. package/agentes/implementador-swl.md +1 -1
  31. package/agentes/investigador-swl.md +432 -432
  32. package/agentes/investigador-ux-swl.md +505 -505
  33. package/agentes/llm-apps-swl.md +1 -1
  34. package/agentes/migrador-swl.md +442 -442
  35. package/agentes/mobile-android-swl.md +511 -511
  36. package/agentes/mobile-cross-swl.md +541 -541
  37. package/agentes/mobile-ios-swl.md +502 -502
  38. package/agentes/mobile-testing-swl.md +302 -302
  39. package/agentes/nemesis-auditor-swl.md +285 -285
  40. package/agentes/notificador-swl.md +1 -1
  41. package/agentes/observabilidad-swl.md +438 -438
  42. package/agentes/pagos-swl.md +310 -310
  43. package/agentes/perfilador-usuario-swl.md +321 -321
  44. package/agentes/planificador-swl.md +399 -399
  45. package/agentes/producto-prd-swl.md +589 -589
  46. package/agentes/red-team-swl.md +218 -218
  47. package/agentes/release-manager-swl.md +590 -590
  48. package/agentes/rendimiento-swl.md +713 -713
  49. package/agentes/resolutor-build-swl.md +10 -1
  50. package/agentes/revisor-angular-swl.md +278 -278
  51. package/agentes/revisor-codigo-swl.md +1 -1
  52. package/agentes/revisor-csharp-swl.md +264 -264
  53. package/agentes/revisor-go-swl.md +259 -259
  54. package/agentes/revisor-java-swl.md +257 -257
  55. package/agentes/revisor-kotlin-swl.md +273 -273
  56. package/agentes/revisor-nextjs-swl.md +281 -281
  57. package/agentes/revisor-php-swl.md +271 -271
  58. package/agentes/revisor-react-swl.md +278 -278
  59. package/agentes/revisor-rust-swl.md +346 -346
  60. package/agentes/revisor-seguridad-swl.md +399 -399
  61. package/agentes/revisor-swift-swl.md +268 -268
  62. package/agentes/revisor-typescript-swl.md +346 -346
  63. package/agentes/sre-swl.md +1 -1
  64. package/agentes/tdd-qa-swl.md +393 -393
  65. package/bin/lib/bot-comandos.js +1 -1
  66. package/bin/swl-ses.js +6 -0
  67. package/comandos/swl/adoptar-proyecto.md +14 -2
  68. package/comandos/swl/configurar-ci.md +8 -1
  69. package/comandos/swl/deuda-codigo.md +97 -97
  70. package/comandos/swl/discutir-fase.md +22 -118
  71. package/comandos/swl/fix.md +118 -0
  72. package/comandos/swl/nuevo-proyecto.md +54 -3
  73. package/comandos/swl/predecir.md +32 -2
  74. package/comandos/swl/seguridad.md +189 -0
  75. package/comandos/swl/status.md +5 -3
  76. package/habilidades/aprendizaje-continuo/SKILL.md +3 -1
  77. package/habilidades/discutir-fase/SKILL.md +84 -81
  78. package/habilidades/discutir-fase/recursos/plantilla-contexto.md +136 -0
  79. package/habilidades/doc-sync/SKILL.md +3 -1
  80. package/habilidades/doubt-driven-review/SKILL.md +15 -1
  81. package/habilidades/ejecutar-task-iterativo/SKILL.md +278 -278
  82. package/habilidades/estructura-proyecto-claude/SKILL.md +11 -2
  83. package/habilidades/harness-claude-code/SKILL.md +3 -1
  84. package/habilidades/instalar-sistema/SKILL.md +3 -1
  85. package/habilidades/meta-reglas-extendido/SKILL.md +92 -0
  86. package/habilidades/meta-reglas-extendido/recursos/analisis-previo-tareas-grandes.md +186 -0
  87. package/habilidades/meta-reglas-extendido/recursos/analizar-directorios-antes-de-escribir.md +235 -0
  88. package/habilidades/meta-reglas-extendido/recursos/api-diseno.md +413 -0
  89. package/habilidades/meta-reglas-extendido/recursos/arquitectura.md +491 -0
  90. package/habilidades/meta-reglas-extendido/recursos/arreglar-al-detectar.md +264 -0
  91. package/habilidades/meta-reglas-extendido/recursos/debatir-antes-de-aceptar.md +152 -0
  92. package/habilidades/meta-reglas-extendido/recursos/git-workflow.md +259 -0
  93. package/habilidades/meta-reglas-extendido/recursos/gobernanza.md +291 -0
  94. package/habilidades/meta-reglas-extendido/recursos/memoria-consolidada.md +263 -0
  95. package/habilidades/meta-reglas-extendido/recursos/seguridad-agentes.md +443 -0
  96. package/habilidades/meta-reglas-extendido/recursos/sesiones-paralelas.md +190 -0
  97. package/habilidades/meta-reglas-extendido/recursos/sin-duplicacion-reglas-globales.md +179 -0
  98. package/habilidades/meta-reglas-extendido/recursos/skills-estandar.md +394 -0
  99. package/habilidades/meta-reglas-extendido/recursos/usar-code-review-graph.md +156 -0
  100. package/habilidades/meta-reglas-extendido/recursos/usar-context7.md +236 -0
  101. package/habilidades/meta-reglas-extendido/recursos/usar-sistema-swl.md +253 -0
  102. package/habilidades/meta-reglas-extendido/recursos/verificar-citas-normativas.md +527 -0
  103. package/habilidades/meta-skills-estandar/SKILL.md +3 -1
  104. package/habilidades/nuevo-proyecto/SKILL.md +20 -3
  105. package/habilidades/php-experto/SKILL.md +10 -3
  106. package/habilidades/{filament-admin/SKILL.md → php-experto/recursos/filament-admin.md} +23 -39
  107. package/habilidades/prevencion-sobreingenieria/recursos/soluciones-nativas.md +166 -166
  108. package/habilidades/prevencion-sobreingenieria/recursos/variables-residuales-post-refactor.md +85 -85
  109. package/habilidades/proceso-debate-adversarial/recursos/personas.md +5 -4
  110. package/habilidades/proceso-ingenieria-requerimientos/SKILL.md +147 -0
  111. package/hooks/check-update.js +19 -10
  112. package/hooks/contexto-subagente.js +68 -68
  113. package/hooks/degradacion-instintos.js +1 -1
  114. package/hooks/extraccion-aprendizajes.js +2 -2
  115. package/hooks/lib/briefing.js +3 -3
  116. package/hooks/lib/nudge-tracker.js +1 -1
  117. package/hooks/lib/otlp-exporter.js +1 -1
  118. package/hooks/lib/webhook-dedup.js +1 -1
  119. package/hooks/session-briefing.js +1 -1
  120. package/llms.txt +6 -6
  121. package/manifiestos/canonical-hashes.json +1043 -52
  122. package/manifiestos/hooks-config.json +469 -469
  123. package/manifiestos/invariantes-criticos.json +30 -30
  124. package/manifiestos/modulos.json +168 -135
  125. package/manifiestos/perfiles.json +0 -2
  126. package/manifiestos/skills-lock.json +49 -56
  127. package/package.json +7 -5
  128. package/plantillas/github-workflows/README.md +15 -1
  129. package/plantillas/github-workflows/swl-devsecops.yml +70 -0
  130. package/plugin.json +5 -5
  131. package/reglas/analisis-previo-tareas-grandes.md +30 -156
  132. package/reglas/analizar-directorios-antes-de-escribir.md +30 -211
  133. package/reglas/api-diseno.md +28 -398
  134. package/reglas/arquitectura.md +35 -456
  135. package/reglas/arreglar-al-detectar.md +30 -230
  136. package/reglas/debatir-antes-de-aceptar.md +30 -143
  137. package/reglas/docs.md +7 -0
  138. package/reglas/estilo-codigo.md +9 -0
  139. package/reglas/fragmentos-compartidos.md +6 -0
  140. package/reglas/git-workflow.md +44 -240
  141. package/reglas/gobernanza.md +23 -262
  142. package/reglas/memoria-consolidada.md +34 -228
  143. package/reglas/performance.md +8 -0
  144. package/reglas/pruebas.md +12 -0
  145. package/reglas/seguridad-agentes.md +37 -418
  146. package/reglas/seguridad.md +12 -0
  147. package/reglas/sesiones-paralelas.md +29 -162
  148. package/reglas/sin-duplicacion-reglas-globales.md +25 -166
  149. package/reglas/skills-estandar.md +23 -373
  150. package/reglas/usar-code-review-graph.md +31 -140
  151. package/reglas/usar-context7.md +30 -208
  152. package/reglas/usar-sistema-swl.md +47 -242
  153. package/reglas/verificar-citas-normativas.md +47 -537
  154. package/scripts/actualizar.js +253 -253
  155. package/scripts/audit-tools/auditar-relleno-inventario.js +145 -0
  156. package/scripts/auditar-clases-conocidas.js +106 -0
  157. package/scripts/bootstrap-instintos.js +2 -2
  158. package/scripts/canario-hooks.js +166 -0
  159. package/scripts/cli/configurar-ci.js +2 -1
  160. package/scripts/evidencia-valor.js +101 -0
  161. package/scripts/field-report.js +18 -2
  162. package/scripts/generar-comandos.js +143 -0
  163. package/scripts/generar-inventario.js +236 -23
  164. package/scripts/generar-matriz-lenguajes.js +1 -1
  165. package/scripts/instalador.js +15 -1
  166. package/scripts/instalar-git-hook.js +8 -1
  167. package/scripts/lib/configurar-ci.js +10 -3
  168. package/scripts/lib/diary-entry.js +3 -1
  169. package/scripts/lib/drift-detector.js +1 -1
  170. package/scripts/lib/evidencia-valor.js +228 -0
  171. package/scripts/lib/expandir-targets.js +71 -71
  172. package/scripts/lib/frontmatter-md.js +63 -0
  173. package/scripts/lib/parsear-opciones.js +2 -0
  174. package/scripts/lib/prune-componentes.js +180 -0
  175. package/scripts/lib/reglas-globales-conocidas.json +16 -2
  176. package/scripts/lib/scoring-instintos.js +2 -2
  177. package/scripts/lib/toml-merge.js +204 -204
  178. package/scripts/lib/transformadores/claude.js +1 -1
  179. package/scripts/lib/transformadores/codex.js +1 -1
  180. package/scripts/lib/transformadores/copilot.js +1 -1
  181. package/scripts/lib/transformadores/cursor.js +1 -1
  182. package/scripts/lib/transformadores/gemini.js +22 -2
  183. package/scripts/lib/transformadores/opencode.js +1 -1
  184. package/scripts/mcp-server/auth.js +105 -105
  185. package/scripts/mcp-server/cache.js +106 -106
  186. package/scripts/prune.js +102 -0
  187. package/scripts/publicar.js +18 -2
  188. package/scripts/tui/index.js +10 -1
  189. package/scripts/tui/pantallas/inspect.js +175 -175
  190. package/scripts/tui/pantallas/install-wizard.js +21 -8
  191. package/scripts/tui/pantallas/uninstall-wizard.js +210 -210
  192. package/scripts/tui/pantallas/update-wizard.js +234 -234
  193. package/scripts/tui/pantallas/welcome.js +188 -189
  194. package/habilidades/paid-media-tracking/SKILL.md +0 -269
  195. package/habilidades/paid-media-tracking/recursos/auditoria-tracking.md +0 -220
  196. package/habilidades/paid-media-tracking/recursos/google-ads-api.md +0 -215
  197. package/habilidades/tracking-measurement/SKILL.md +0 -239
  198. package/habilidades/tracking-measurement/recursos/consent-mode.md +0 -231
  199. package/habilidades/tracking-measurement/recursos/gtm-datalayer.md +0 -216
  200. package/habilidades/tracking-measurement/recursos/meta-capi.md +0 -262
@@ -9,401 +9,31 @@ paths:
9
9
  ---
10
10
  # Regla: Diseño de APIs REST
11
11
 
12
- Esta regla es OBLIGATORIA para toda API REST expuesta, ya sea pública o interna.
13
- Una API mal diseñada es difícil de versionar, de mantener y de consumir.
14
- El costo de corregir un contrato de API en producción es enormemente más alto
15
- que diseñarlo bien desde el inicio. Ningún endpoint se considera listo si viola
16
- cualquiera de los puntos aquí listados.
17
-
18
- ---
19
-
20
- ## Versionado obligatorio con prefijo de URL
21
-
22
- Toda API debe incluir el número de versión en la URL desde el primer endpoint.
23
-
24
- - El versionado va en el prefijo de la URL como número entero:
25
- `/v1/`, `/v2/`, `/v3/`, etc.
26
- - Formato correcto:
27
- ```
28
- https://api.miapp.com/v1/usuarios
29
- https://api.miapp.com/v1/pedidos/123/items
30
- ```
31
- - Formato incorrecto:
32
- ```
33
- https://api.miapp.com/usuarios (sin versión imposible de versionar después)
34
- https://api.miapp.com/v1.2/usuarios (versión minor en URL innecesariamente granular)
35
- https://api.miapp.com/usuarios?v=1 (versión en query param rompe el caching)
36
- ```
37
- - El versionado en headers (`API-Version: 1`) se permite como mecanismo secundario
38
- pero NUNCA como el único — los logs, el caching y los proxies operan sobre URLs.
39
- - Al lanzar una nueva versión major (`/v2/`), mantener `/v1/` funcional con un
40
- período de deprecación documentado de mínimo 6 meses.
41
- - Comunicar la deprecación en los headers de respuesta:
42
- `Deprecation: true`, `Sunset: [fecha]`, `Link: </v2/usuarios>; rel="successor-version"`
43
-
44
- ---
45
-
46
- ## Respuestas consistentes con envelope estándar
47
-
48
- Todas las respuestas de la API deben seguir el mismo formato de envelope.
49
-
50
- ### Respuesta exitosa con un objeto
51
-
52
- ```json
53
- {
54
- "data": {
55
- "id": "550e8400-e29b-41d4-a716-446655440000",
56
- "nombre": "Juan Pérez",
57
- "email": "juan@ejemplo.com"
58
- },
59
- "meta": {
60
- "request_id": "req_abc123",
61
- "timestamp": "2026-03-25T14:30:00Z",
62
- "version": "1.0"
63
- }
64
- }
65
- ```
66
-
67
- ### Respuesta exitosa con lista (paginada)
68
-
69
- ```json
70
- {
71
- "data": [...],
72
- "meta": {
73
- "request_id": "req_abc123",
74
- "timestamp": "2026-03-25T14:30:00Z",
75
- "total": 150,
76
- "page": 1,
77
- "per_page": 20,
78
- "has_next": true,
79
- "has_prev": false
80
- }
81
- }
82
- ```
83
-
84
- ### Respuesta de error
85
-
86
- ```json
87
- {
88
- "errors": [
89
- {
90
- "code": "VALIDATION_ERROR",
91
- "message": "El campo 'email' no tiene formato válido",
92
- "field": "email",
93
- "detail": "El valor 'juan-sin-arroba' no es una dirección de correo electrónico"
94
- }
95
- ],
96
- "meta": {
97
- "request_id": "req_abc123",
98
- "timestamp": "2026-03-25T14:30:00Z"
99
- }
100
- }
101
- ```
102
-
103
- - NUNCA devolver `{"success": true, "data": [...]}` — usar el status HTTP para indicar éxito.
104
- - NUNCA devolver `{"error": "algo falló"}` sin código de error y detalle.
105
- - El campo `meta.request_id` es OBLIGATORIO — permite correlacionar logs con errores reportados por clientes.
106
- - El campo `data` puede ser `null` en respuestas 204 No Content.
107
- - En FastAPI: crear un schema `APIResponse[T]` genérico y usarlo en todos los endpoints.
108
- - En Express/NestJS: crear un interceptor o middleware que envuelva todas las respuestas.
109
-
110
- ---
111
-
112
- ## Paginación obligatoria en endpoints de listado
113
-
114
- Ningún endpoint que devuelva una colección puede hacerlo sin paginación.
115
-
116
- - Todo endpoint que devuelva un array DEBE soportar paginación. Sin excepción.
117
- Sin paginación, la base de datos crece y el endpoint eventualmente colapsa.
118
-
119
- ### Paginación basada en cursor (preferida para listas grandes o en tiempo real)
120
-
121
- ```
122
- GET /v1/pedidos?cursor=eyJpZCI6MTIzfQ==&limit=20
123
- ```
124
-
125
- Ventajas: consistente bajo inserciones concurrentes, eficiente para grandes datasets.
126
-
127
- ```json
128
- {
129
- "data": [...],
130
- "meta": {
131
- "next_cursor": "eyJpZCI6MTQzfQ==",
132
- "prev_cursor": "eyJpZCI6MTAzfQ==",
133
- "has_next": true,
134
- "has_prev": true,
135
- "limit": 20
136
- }
137
- }
138
- ```
139
-
140
- ### Paginación por offset (aceptable para datasets pequeños y UIs con número de página)
141
-
142
- ```
143
- GET /v1/productos?page=3&per_page=20
144
- ```
145
-
146
- ```json
147
- {
148
- "data": [...],
149
- "meta": {
150
- "page": 3,
151
- "per_page": 20,
152
- "total": 150,
153
- "total_pages": 8,
154
- "has_next": true,
155
- "has_prev": true
156
- }
157
- }
158
- ```
159
-
160
- - El `per_page` máximo es 100 registros. NUNCA permitir devolver registros ilimitados.
161
- - El `per_page` por defecto es 20 si no se especifica.
162
- - Si el cliente pide un `per_page` mayor al máximo, devolver el máximo silenciosamente
163
- o devolver 400 Bad Request con mensaje explicativo. Documentar cuál de las dos.
164
- - NUNCA usar `limit=0` para devolver todos los registros — eso rompe el propósito de la paginación.
165
-
166
- ---
167
-
168
- ## Filtros y ordenamiento estandarizados
169
-
170
- Los parámetros de filtrado y ordenamiento siguen convenciones uniformes en toda la API.
171
-
172
- ### Filtros
173
-
174
- ```
175
- GET /v1/pedidos?estatus=pendiente&cliente_id=abc123&fecha_desde=2026-01-01&fecha_hasta=2026-03-31
176
- ```
177
-
178
- - Los filtros van como query parameters en GET. NUNCA en el body de un GET.
179
- - Los nombres de los filtros coinciden con los nombres de campo del recurso.
180
- - Para rangos: usar sufijos `_desde` y `_hasta` (o `_min` / `_max` para números).
181
- - Para múltiples valores del mismo campo: repetir el parámetro o usar coma como separador.
182
- Documentar cuál se usa. No mezclar ambas convenciones:
183
- ```
184
- ?estatus=activo&estatus=pendiente (repetición — más estándar)
185
- ?estatus=activo,pendiente (coma — más compacto)
186
- ```
187
- - Los filtros que no existen o tienen valores inválidos devuelven 400 Bad Request
188
- con un mensaje que indica exactamente cuál parámetro es inválido.
189
-
190
- ### Ordenamiento
191
-
192
- ```
193
- GET /v1/pedidos?sort=fecha_creacion&order=desc
194
- ```
195
-
196
- - Parámetro `sort`: nombre del campo por el que ordenar.
197
- - Parámetro `order`: `asc` (por defecto) o `desc`.
198
- - Para ordenamiento multi-campo:
199
- ```
200
- GET /v1/pedidos?sort=estatus,fecha_creacion&order=asc,desc
201
- ```
202
- - Si se pide ordenar por un campo que no existe: 400 Bad Request.
203
- - Si se pide ordenar por un campo que no es indexado y la tabla tiene >10k registros,
204
- documentar esta limitación y devolver un error descriptivo.
205
-
206
- ---
207
-
208
- ## HTTP status codes correctos
209
-
210
- El status code es la primera línea de comunicación del resultado. Usarlo correctamente.
211
-
212
- ```
213
- 200 OK — GET exitoso, PUT/PATCH exitoso con body en respuesta
214
- 201 Created — POST exitoso que crea un recurso. Incluir header Location con URL del nuevo recurso
215
- 204 No Content — DELETE exitoso, PUT/PATCH exitoso sin body
216
- 400 Bad Request — Error de validación, parámetro inválido, body malformado
217
- 401 Unauthorized — No autenticado (falta token o token inválido)
218
- 403 Forbidden — Autenticado pero sin permiso para este recurso/acción
219
- 404 Not Found — El recurso no existe
220
- 409 Conflict — Conflicto de estado (ej: email duplicado, stock insuficiente)
221
- 410 Gone — El recurso existió pero fue eliminado permanentemente
222
- 422 Unprocessable Entity — La sintaxis es válida pero la semántica falla (ej: fecha de inicio > fecha de fin)
223
- 429 Too Many Requests — Rate limit alcanzado
224
- 500 Internal Server Error — Error interno no esperado (con request_id para seguimiento)
225
- 503 Service Unavailable — Servicio temporalmente no disponible (mantenimiento, dependencia caída)
226
- ```
227
-
228
- Errores comunes a EVITAR:
229
- - NUNCA devolver 200 con `{"success": false}` — usar el status code correcto.
230
- - NUNCA devolver 500 para errores de validación de input del cliente — esos son 400/422.
231
- - NUNCA devolver 404 cuando el problema es falta de permisos — eso es 403.
232
- (Excepción: cuando revelar la existencia del recurso es un problema de seguridad)
233
- - NUNCA devolver 401 cuando el usuario está autenticado pero no tiene permiso — eso es 403.
234
-
235
- ---
236
-
237
- ## Rate limiting obligatorio en endpoints públicos
238
-
239
- Todo endpoint accesible sin autenticación o con autenticación débil debe tener rate limiting.
240
-
241
- - Los endpoints públicos (sin autenticación) tienen rate limiting estricto:
242
- Máximo 60 requests por minuto por IP como punto de partida.
243
- Ajustar según el caso de uso real.
244
- - Los endpoints autenticados tienen rate limiting por usuario/token:
245
- Máximo 1000 requests por minuto por usuario autenticado.
246
- - Los endpoints de autenticación (login, registro, recuperación de contraseña)
247
- tienen rate limiting especialmente estricto:
248
- Máximo 5 intentos por minuto por IP, con bloqueo temporal de 15 minutos al superar.
249
- - Comunicar el rate limiting en headers de respuesta:
250
- ```
251
- X-RateLimit-Limit: 60
252
- X-RateLimit-Remaining: 45
253
- X-RateLimit-Reset: 1711379400
254
- Retry-After: 30 (solo en respuestas 429)
255
- ```
256
- - La respuesta al superar el rate limit es siempre 429 Too Many Requests con body:
257
- ```json
258
- {
259
- "errors": [{
260
- "code": "RATE_LIMIT_EXCEEDED",
261
- "message": "Demasiadas solicitudes. Intenta de nuevo en 30 segundos.",
262
- "detail": "Límite: 60 solicitudes por minuto"
263
- }]
264
- }
265
- ```
266
- - El rate limiting se implementa en el gateway o proxy (nginx, Kong, AWS API Gateway),
267
- no en la lógica de aplicación. La lógica de aplicación es el último recurso.
268
-
269
- ---
270
-
271
- ## CORS configurado explícitamente
272
-
273
- El navegador solo permite requests cross-origin si el servidor lo autoriza explícitamente.
274
-
275
- - La lista de orígenes permitidos se define por ambiente y se configura desde
276
- variables de entorno, NUNCA hardcodeada en el código:
277
- ```python
278
- # FastAPI
279
- origins = os.getenv("CORS_ORIGINS", "").split(",")
280
- app.add_middleware(CORSMiddleware, allow_origins=origins, ...)
281
- ```
282
- - NUNCA usar `allow_origins=["*"]` en producción. Esto permite que cualquier sitio
283
- haga requests a la API en nombre del usuario.
284
- - `allow_credentials=True` solo cuando sea necesario (cuando se usan cookies de sesión).
285
- Incompatible con `allow_origins=["*"]`.
286
- - Los métodos permitidos deben ser los mínimos necesarios:
287
- APIs de solo lectura: `["GET", "OPTIONS"]`
288
- APIs completas: `["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]`
289
- - Los headers permitidos deben listarse explícitamente si no se usan los estándar.
290
- - El preflight request (OPTIONS) debe responder correctamente antes de que el browser
291
- envíe el request real.
292
- - En APIs públicas de lectura sin credenciales, `allow_origins=["*"]` puede ser
293
- aceptable. Documentar explícitamente por qué se decidió así.
294
-
295
- ---
296
-
297
- ## Documentación OpenAPI siempre actualizada
298
-
299
- La documentación es parte del contrato de la API. Si está desactualizada, no es documentación.
300
-
301
- - La especificación OpenAPI debe generarse desde el código, no escribirse manualmente.
302
- En FastAPI: se genera automáticamente desde los schemas y decoradores.
303
- En Express: usar `swagger-jsdoc` o `tsoa`.
304
- - Cada endpoint debe tener:
305
- - `summary`: descripción corta de qué hace
306
- - `description`: detalles, casos edge, consideraciones de negocio
307
- - `tags`: agrupación por dominio (`Usuarios`, `Pedidos`, `Auth`)
308
- - Todos los parámetros documentados con tipo, formato y si son requeridos
309
- - Todos los posibles status codes de respuesta con su schema
310
- - Ejemplos de request y response para los casos principales
311
- - Los schemas de request y response deben documentar:
312
- - Qué campos son requeridos vs opcionales
313
- - Restricciones de longitud, formato y dominio de valores
314
- - Descripciones en español claras para cada campo
315
- - La documentación está disponible en `/docs` (Swagger UI) y `/redoc` en ambientes
316
- de desarrollo y staging. En producción, solo si la API es pública.
317
- - Los cambios de API sin actualizar la documentación no pasan code review.
318
- - Los schemas de OpenAPI se validan en CI para detectar documentación rota.
319
-
320
- ---
321
-
322
- ## Error responses con código, mensaje y detalle
323
-
324
- Los errores deben ser diagnósticables por el cliente sin acceso a los logs del servidor.
325
-
326
- Cada error response incluye:
327
-
328
- ```json
329
- {
330
- "errors": [
331
- {
332
- "code": "CÓDIGO_EN_SNAKE_CASE_MAYÚSCULAS",
333
- "message": "Mensaje legible por humanos en español",
334
- "field": "nombre_del_campo",
335
- "detail": "Información adicional para debugging"
336
- }
337
- ],
338
- "meta": {
339
- "request_id": "req_abc123",
340
- "timestamp": "2026-03-25T14:30:00Z"
341
- }
342
- }
343
- ```
344
-
345
- - `code`: identificador de máquina para el tipo de error. En SCREAMING_SNAKE_CASE.
346
- Ejemplos: `VALIDATION_ERROR`, `RESOURCE_NOT_FOUND`, `INSUFFICIENT_STOCK`,
347
- `EMAIL_ALREADY_EXISTS`, `INVALID_CREDENTIALS`, `RATE_LIMIT_EXCEEDED`.
348
- - `message`: mensaje en lenguaje natural, legible por el usuario final si aplica.
349
- Sin jerga técnica. NUNCA exponer stack traces o nombres de tablas de BD.
350
- - `field`: nombre del campo que causó el error (solo para errores de validación).
351
- Si el error no está asociado a un campo específico, omitir este campo.
352
- - `detail`: información técnica adicional para el desarrollador cliente. Puede ser
353
- más técnico que `message`. Opcional.
354
- - Para errores de validación con múltiples campos inválidos, devolver TODOS los errores
355
- en el array, no solo el primero. El cliente necesita corregir todo de una vez.
356
- - Para errores 500: el mensaje es genérico ("Error interno del servidor").
357
- El `request_id` permite correlacionar con los logs del servidor donde está el detalle real.
358
- NUNCA exponer detalles del error interno al cliente en producción.
359
- - Los códigos de error deben estar documentados en la spec de OpenAPI.
360
-
361
- ---
362
-
363
- ## Nomenclatura de recursos y endpoints
364
-
365
- Las URLs deben ser predecibles, consistentes y orientadas a recursos, no a acciones.
366
-
367
- - Los recursos se expresan en sustantivos en plural, en español (o inglés, pero consistente):
368
- `/v1/usuarios`, `/v1/pedidos`, `/v1/productos`
369
- - Las acciones CRUD mapean a métodos HTTP, no a verbos en la URL:
370
- ```
371
- GET /v1/pedidos — listar pedidos
372
- POST /v1/pedidos — crear pedido
373
- GET /v1/pedidos/123 — obtener pedido específico
374
- PUT /v1/pedidos/123 — reemplazar pedido completo
375
- PATCH /v1/pedidos/123 — actualizar campos específicos del pedido
376
- DELETE /v1/pedidos/123 — eliminar pedido
377
- ```
378
- - Los sub-recursos se expresan anidando en la URL:
379
- ```
380
- GET /v1/pedidos/123/items — items del pedido 123
381
- POST /v1/pedidos/123/items — agregar item al pedido 123
382
- ```
383
- - Para acciones que no mapean limpiamente a CRUD, usar sub-recursos orientados
384
- a la acción como nombre:
385
- ```
386
- POST /v1/pedidos/123/cancelar — cancelar el pedido 123
387
- POST /v1/usuarios/123/activar — activar cuenta del usuario 123
388
- ```
389
- Preferir esto a meter `?action=cancelar` en query params.
390
- - Los IDs en las URLs deben ser UUIDs o IDs opacos. NUNCA IDs secuenciales que
391
- exponen el volumen de datos del sistema.
392
- - Las URLs son case-insensitive por convención, pero usar siempre minúsculas con guiones:
393
- `/v1/tipos-de-pago` no `/v1/TiposDePago` ni `/v1/tipos_de_pago`.
394
-
395
- ---
396
-
397
- ## Checklist antes de exponer un endpoint nuevo
398
-
399
- - [ ] La URL sigue la convención de recursos y tiene el prefijo `/v{N}/`
400
- - [ ] El método HTTP es el correcto para la operación (GET no modifica datos)
401
- - [ ] La respuesta usa el envelope estándar `{data, meta}` o `{errors, meta}`
402
- - [ ] El endpoint de listado tiene paginación implementada
403
- - [ ] El status code de respuesta es el correcto para cada caso
404
- - [ ] Los errores de validación devuelven 400/422 con todos los campos inválidos
405
- - [ ] El endpoint tiene autenticación si maneja datos no públicos
406
- - [ ] El endpoint está documentado en OpenAPI con todos los parámetros y responses
407
- - [ ] El rate limiting está configurado (si es público o de autenticación)
408
- - [ ] El CORS está configurado correctamente para los orígenes esperados
409
- - [ ] Los IDs expuestos son UUIDs u opacos, no IDs secuenciales
12
+ Obligatoria para toda API REST expuesta, pública o interna. Ningún endpoint está listo si viola estos puntos: corregir un contrato en producción cuesta mucho más que diseñarlo bien desde el inicio.
13
+
14
+ ## Normas duras
15
+
16
+ - **Versionado**: prefijo entero en la URL (`/v1/`, `/v2/`) desde el primer endpoint. Header `API-Version` solo como mecanismo secundario, nunca el único. Al lanzar `/v2/`, mantener `/v1/` mínimo 6 meses con headers `Deprecation`, `Sunset` y `Link` (successor-version).
17
+ - **Envelope estándar** en toda respuesta: éxito `{data, meta}`, error `{errors[], meta}`. `meta.request_id` es OBLIGATORIO (correlaciona logs con errores de clientes). Implementarlo una sola vez: schema genérico (FastAPI) o interceptor/middleware (Express/NestJS).
18
+ - **Paginación** en TODO endpoint que devuelva colección, sin excepción: cursor (preferida para listas grandes o en tiempo real) u offset `page`/`per_page` (datasets pequeños). `per_page` default 20, máximo 100; documentar si el exceso se recorta o devuelve 400.
19
+ - **Filtros**: query params en GET con nombres iguales a los campos del recurso; rangos con sufijos `_desde`/`_hasta` (o `_min`/`_max`); multi-valor por repetición del parámetro o coma — documentar cuál y no mezclar. Filtro inexistente o inválido → 400 indicando el parámetro.
20
+ - **Ordenamiento**: `sort` (campo) + `order` (`asc` default, `desc`); multi-campo con listas separadas por coma. Campo inexistente → 400; campo no indexado en tablas >10k registros → documentar la limitación y devolver error descriptivo.
21
+ - **Status codes esenciales**: 200 GET/PUT/PATCH con body · 201 POST que crea (+header `Location`) · 204 sin body (DELETE) · 400 validación/body malformado · 401 no autenticado · 403 autenticado sin permiso · 404 no existe · 409 conflicto de estado · 410 eliminado permanente · 422 sintaxis válida pero semántica inválida · 429 rate limit · 500 error interno (+`request_id`) · 503 no disponible.
22
+ - **Errores**: cada entrada con `code` (SCREAMING_SNAKE_CASE, documentado en OpenAPI), `message` legible sin jerga técnica, `field` (solo validación) y `detail` opcional. Validación devuelve TODOS los campos inválidos en el array, no solo el primero. 500 con mensaje genérico + `request_id`.
23
+ - **Rate limiting** implementado en gateway/proxy (no en la app): públicos 60 req/min/IP, autenticados 1000 req/min/usuario, endpoints de auth 5 intentos/min/IP con bloqueo de 15 min. Comunicar con headers `X-RateLimit-*` y `Retry-After` (429 con body de error estándar).
24
+ - **CORS**: whitelist explícita de orígenes desde variables de entorno por ambiente; métodos y headers mínimos necesarios; `allow_credentials=True` solo con cookies de sesión (incompatible con `*`); preflight OPTIONS correcto.
25
+ - **OpenAPI generada desde el código** (no manual), con `summary`, `description`, `tags`, parámetros, todos los status codes con schema y ejemplos; disponible en `/docs`/`/redoc` en dev/staging (en producción solo si la API es pública); validada en CI. Cambios de API sin actualizar la doc no pasan code review.
26
+ - **Nomenclatura**: recursos como sustantivos en plural (idioma consistente); CRUD mapea a métodos HTTP, no a verbos en la URL; sub-recursos anidados (`/v1/pedidos/123/items`); acciones no-CRUD como `POST /recurso/{id}/accion` (nunca `?action=`); URLs en minúsculas con guiones; IDs UUID u opacos.
27
+
28
+ ## NUNCA / SIEMPRE
29
+
30
+ - NUNCA URL sin versión, versión en query param, ni versión minor en la URL.
31
+ - NUNCA `{"success": true/false}` ni `{"error": "..."}` sin código y detalle — el status HTTP indica el resultado.
32
+ - NUNCA colecciones sin paginación ni `limit=0` como "todos los registros".
33
+ - NUNCA 200 con error, 500 para validación del cliente (400/422), 404 por falta de permisos (403, salvo que revelar existencia sea riesgo de seguridad), ni 401 estando autenticado sin permiso (403).
34
+ - NUNCA filtros en el body de un GET.
35
+ - NUNCA `allow_origins=["*"]` en producción (excepción documentada: API pública de solo lectura sin credenciales) ni orígenes hardcodeados.
36
+ - NUNCA exponer stack traces, nombres de tablas ni detalles internos al cliente.
37
+ - NUNCA IDs secuenciales en URLs exponen el volumen de datos del sistema.
38
+
39
+ Detalle extendido (ejemplos completos, tablas de códigos, checklist pre-endpoint, casos): `Skill("meta-reglas-extendido")` `recursos/api-diseno.md`.