|
| 1 | +# CONTEXT — AyudaPy |
| 2 | + |
| 3 | +## Estado actual |
| 4 | +- Proyecto en mantenimiento — features congeladas desde 2020 |
| 5 | +- Actividad reciente: solo bumps de seguridad (Dependabot) |
| 6 | +- 2 PRs de seguridad pendientes de merge (#376 Django 4.2.28, #377 Pillow 12.1.1) |
| 7 | +- 27 issues abiertos (todos de abril-mayo 2020) |
| 8 | +- Tests vacíos (core/tests.py, org/tests.py) |
| 9 | + |
| 10 | +## Auditoría de seguridad (2026-03-24) |
| 11 | + |
| 12 | +### CRÍTICOS |
| 13 | +1. **Teléfonos expuestos vía API sin auth** — core/serializers.py:10, org/serializers.py:9,15. GET público retorna phone de todos los solicitantes |
| 14 | +2. **API sin rate limiting ni permisos** — REST_FRAMEWORK no define DEFAULT_PERMISSION_CLASSES ni DEFAULT_THROTTLE_CLASSES. Todos los endpoints abiertos incluyendo CRUD de devices |
| 15 | +3. **ALLOWED_HOSTS = ['*']** — conf/settings.py:29. Host Header Injection. Sin SECURE_HSTS, SESSION_COOKIE_SECURE, CSRF_COOKIE_SECURE, CSRF_TRUSTED_ORIGINS |
| 16 | + |
| 17 | +### ALTOS |
| 18 | +4. **DEBUG_PROPAGATE_EXCEPTIONS = True** — conf/settings.py:31. Stack traces expuestos |
| 19 | +5. **Geocoding síncrono sin timeout en save()** — core/models.py:125-140, org/models.py:48-60,111-123,165-177. Bloquea requests, DoS vector. En org/ no tiene try/except |
| 20 | +6. **api_settings no importado** — core/api.py:149. NameError en POST /api/v1/devices/ |
| 21 | +7. **Docker EOL** — python:3.9-buster, sin multi-stage, sin user no-root, sin healthcheck |
| 22 | + |
| 23 | +### MEDIOS |
| 24 | +8. Queries sin límite — core/views.py:165 (TODO del autor) |
| 25 | +9. Middleware silencia errores — core/middleware.py:27-32 (except: pass) |
| 26 | +10. device.save(device) bug — core/middleware.py:92 |
| 27 | +11. Headers seguridad ausentes (HSTS, CSP, cookie flags) |
| 28 | +12. Dependencias antiguas (geopy 1.21, django-filter 2.4, django-environ 0.4.5) |
| 29 | + |
| 30 | +## Auditoría frontend (2026-03-24) |
| 31 | + |
| 32 | +### CRÍTICOS |
| 33 | +1. **XSS vía innerHTML** — templates/help_request/create.html:75-79 (API geocoding sin sanitizar), static/scripts/list.js:204-216 y list-donation.js:193-215 (popup markers sin sanitizar). sanitizeHTML() existe en table-view.js pero no se usa |
| 34 | +2. **Validación client-side insuficiente** — create.html:151-172, sin feedback visual, sin prevención de doble submit |
| 35 | + |
| 36 | +### ALTOS |
| 37 | +3. **Accesibilidad** — base.html sin lang="es", 6+ imágenes sin alt, `<p onclick>` en post.html (no accesible), sin aria-required/aria-invalid en forms |
| 38 | +4. **JS duplicado 95%** — list.js (316 LOC) y list-donation.js (305 LOC) son copy-paste |
| 39 | +5. **Librerías deprecated** — Bulma 0.8.0 (2020), Moment.js 2.24.0 (deprecated), BulmaJS 0.10.3 (2019) |
| 40 | +6. **Performance** — ~15-20 HTTP requests, ~300KB+, sin lazy loading, scripts sin async/defer, Leaflet cargado en páginas sin mapa, 130 líneas CSS inline en base.html |
| 41 | + |
| 42 | +### MEDIOS |
| 43 | +7. JS legacy — charCode deprecated (list.js:75), console.log en prod (list.js:123), Date.prototype mutado (list.js:159), variable global implícita (create.html:91) |
| 44 | +8. Sin debounce en búsqueda — list.js:174, cada Enter dispara API call sin throttle |
| 45 | + |
| 46 | +## Plan de contribución |
| 47 | + |
| 48 | +### Fase 1 — Seguridad (completada 2026-03-24) |
| 49 | +- [x] Excluir `phone` de serializers REST (core + org) y de search_fields en API |
| 50 | +- [x] Agregar DEFAULT_PERMISSION_CLASSES y DEFAULT_THROTTLE_CLASSES (100/h anon, 300/h user) |
| 51 | +- [x] Configurar ALLOWED_HOSTS via env (default localhost) |
| 52 | +- [x] Remover DEBUG_PROPAGATE_EXCEPTIONS |
| 53 | +- [x] Agregar timeout=5 a Nominatim + try/except en org/models.py (3 modelos) y core/models.py |
| 54 | +- [x] Fix import api_settings en core/api.py |
| 55 | +- [x] Agregar headers de seguridad (HSTS, SESSION/CSRF_COOKIE_SECURE, X_FRAME_OPTIONS=DENY) |
| 56 | +- [x] Fix search_fields en org/api.py ('title' no existe en DonationCenter → 'name') |
| 57 | +- [x] Fix BaseResource.save() accedía a self.phone sin tenerlo (hasattr check) |
| 58 | +- [x] Fix device.save(device) → device.save() en middleware |
| 59 | + |
| 60 | +### Fase 1b — Seguridad frontend (completada 2026-03-24) |
| 61 | +- [x] Sanitizar innerHTML: escapeHTML() en create.html (geocoding API), sanitizeHTML() exportada desde table-view.js y usada en popups de list.js y list-donation.js |
| 62 | +- [x] Prevención de doble submit: onsubmit="return checkRequestForm()" en help_request/create.html y donation_center/create.html |
| 63 | +- [x] Remover console.log con coordenadas en list.js y list-donation.js |
| 64 | +- [x] encodeURIComponent en URL de geocoding (create.html) |
| 65 | +- [x] parseInt en pk de popups (list.js, list-donation.js) para evitar inyección en href |
| 66 | + |
| 67 | +### Fase 2 — Infraestructura |
| 68 | +- [ ] Actualizar Docker: python:3.12-slim, multi-stage, no-root user, healthchecks |
| 69 | +- [ ] Actualizar dependencias antiguas (geopy 2.x, django-filter 24.x) |
| 70 | +- [ ] Fix middleware silencioso (except: pass sin logging) |
| 71 | +- [ ] Mergear PRs pendientes de seguridad (#376, #377) |
| 72 | + |
| 73 | +### Fase 3 — Tests |
| 74 | +- [ ] Tests para modelos (HelpRequest, DonationCenter) |
| 75 | +- [ ] Tests para API endpoints |
| 76 | +- [ ] Tests para formularios y vistas |
| 77 | + |
| 78 | +### Fase 4 — Frontend cleanup (parcial 2026-03-24) |
| 79 | +- [x] Agregar lang="es" a `<html>` en base.html |
| 80 | +- [x] Alt text en todas las imágenes (logo, footer, details thumbnail, phone img) |
| 81 | +- [x] Convertir `<p onclick>` a `<button type="button">` con aria-label en post.html |
| 82 | +- [x] Fix login.html class duplicado (Bulma+Bootstrap → solo Bulma) |
| 83 | +- [x] Remover borde debug verde en list.html y donation_center/list.html |
| 84 | +- [x] Agregar defer a scripts bloqueantes (fontawesome, bulmajs, moment) |
| 85 | +- [x] Aria-labels: loading indicator (role=status), cities input, role=search en dropdowns |
| 86 | +- [x] Error handling en fetch (catch para ocultar spinner en list.js y list-donation.js) |
| 87 | +- [x] Aria-label en delete button de notificaciones (details.html) |
| 88 | +- [ ] Refactorizar list.js y list-donation.js en módulo compartido |
| 89 | +- [ ] Reemplazar Moment.js por Day.js o formateo nativo |
| 90 | +- [ ] Agregar loading="lazy" a imágenes |
| 91 | +- [ ] Mover CSS inline de base.html a archivo separado |
| 92 | +- [ ] Agregar debounce a búsqueda |
| 93 | +- [ ] Fix charCode → e.key, Date.prototype, variable global |
| 94 | +- [ ] Extraer colores hardcoded a variables CSS |
| 95 | +- [ ] i18n: strings hardcoded en donation_center templates |
| 96 | + |
| 97 | +### Fase 5 — Features (issues abiertos prioritarios) |
| 98 | +- [ ] #295 Filtro por departamento/provincia |
| 99 | +- [ ] #241 Categorías en API |
| 100 | +- [ ] #157 Expiración de pedidos |
| 101 | +- [ ] #167 Ciudades vía AJAX |
| 102 | +- [ ] #288 Fix ciudades con error 502 |
| 103 | + |
| 104 | +## Issues abiertos (27 total, todos de abril-mayo 2020) |
| 105 | + |
| 106 | +### Critical path |
| 107 | +- #295 Filtro por departamento/provincia |
| 108 | +- #182 Campos uso interno para users logueados |
| 109 | +- #76 Registro de usuario |
| 110 | + |
| 111 | +### Features |
| 112 | +- #250 POST y AUTH en API | #241 Categorías en API | #272 Buscar por id/name |
| 113 | +- #257 Sauron Mode (zoom sin límite auth) | #210 Leaflet.awesome-markers |
| 114 | +- #229 Solo thumbnails | #200 Migrar a S3/Spaces | #197 CI/CD Jenkins |
| 115 | +- #167 Ciudades vía AJAX | #157 Expiración pedidos | #150 Filtro fechas |
| 116 | +- #145 db_index en User/Device | #127 Mis Pedidos | #126 Mi Perfil |
| 117 | +- #74 Columnas status HelpRequest | #68 Lista pendientes/asistidos |
| 118 | +- #25 Filtro ventana temporal | #165 2FA admin | #123 Consultas BD internas |
| 119 | + |
| 120 | +### Bugs |
| 121 | +- #288 Ciudades con error 502 (~15 ciudades) |
| 122 | +- #270 Ubicación no se borra en mapa |
| 123 | +- #184 Error crear usuarios en admin |
| 124 | + |
| 125 | +### Good first issue |
| 126 | +- #294 Traducir I18N-GUIDE a español |
| 127 | +- #272 Agregar id/name a búsqueda |
| 128 | +- #241 Categorías en API |
| 129 | + |
| 130 | +### Descartados |
| 131 | +- #64 Ollas populares (wontfix) | #33 Campo confiable (duplicate) |
| 132 | + |
| 133 | +### PRs abiertos |
| 134 | +- #377 Bump Pillow 12.1.1 (seguridad) | #376 Bump Django 4.2.28 (seguridad) |
| 135 | +- #281 Ollas populares (duplicate) | #268 Terser JS minifier (draft) |
| 136 | +- #166 2FA admin (bugs pendientes) |
| 137 | + |
| 138 | +## Pendiente |
| 139 | +- Contactar al owner (melizeche) antes de PRs grandes |
| 140 | +- Verificar si hay ambiente de staging/producción activo |
0 commit comments