Skip to content

feat(resources): cooldown de reapertura de disputa + rate-limit en reportes de validez#256

Open
nopestack wants to merge 5 commits into
GlobalEmergency:mainfrom
nopestack:feature/173-dispute-cooldown-ratelimit
Open

feat(resources): cooldown de reapertura de disputa + rate-limit en reportes de validez#256
nopestack wants to merge 5 commits into
GlobalEmergency:mainfrom
nopestack:feature/173-dispute-cooldown-ratelimit

Conversation

@nopestack

Copy link
Copy Markdown
Contributor

Closes #173

Resumen

Implementa las dos medidas anti-abuso pendientes del EPIC #120 (§4 Futuro).

Cooldown de reapertura

  • Migración `0043_resource_dispute_cooldown.sql`: columna nullable `dispute_dismissed_at timestamptz` en `resources`.
  • `Resource.clearDispute('dismiss')` guarda la marca de tiempo en `_disputeDismissedAt` (solo en `dismiss`; `confirm_closed` y `mark_invalid` no la tocan).
  • `Resource.flagDisputed(cooldownMs)`: si `cooldownMs > 0` y el punto fue descartado dentro de la ventana, el re-disputado es un no-op (no emite evento, `disputed` permanece `false`).
  • `ReportResourceValidity` acepta `cooldownMs` (6.º parámetro, default 0) y lo pasa a `flagDisputed()`. Ahora devuelve `current.disputed` (no `true` hardcodeado) para reflejar fielmente el estado tras el posible no-op.
  • `RESOURCE_DISPUTE_COOLDOWN_HOURS` configura la ventana en horas vía variable de entorno (0 = sin cooldown).

Rate-limit

  • Throttler nombrado `validity` registrado en `app.module.ts`: 20 peticiones/hora por IP.
  • `POST /resources/:resourceId/validity-reports` protegido con `@UseGuards(ThrottlerGuard)` + `@Throttle({ validity: … })`, siguiendo el patrón ya establecido para `auth` e `intake`.
  • Deshabilitado en entorno `test` (igual que los throttlers existentes).

Plan de pruebas

  • `resource-dispute.spec.ts`: 4 nuevos tests — `clearDispute('dismiss')` activa `disputeDismissedAt`; `confirm_closed` no lo activa; cooldown activo es no-op; cooldown expirado disputa con normalidad; round-trip de snapshot
  • `report-resource-validity.spec.ts`: cooldown activo suprime la disputa en el flujo completo del caso de uso
  • Build TypeScript estricto, ESLint y Prettier sin errores
  • 1315 tests pasando, migración `0043` aplicada en global-setup

@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

@nopestack is attempting to deploy a commit to the GlobalEmergency Team on Vercel.

A member of the Team first needs to authorize it.

@nopestack nopestack marked this pull request as ready for review June 30, 2026 13:19
@nopestack nopestack requested a review from vgpastor as a code owner June 30, 2026 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Disputa: cooldown de reapertura y rate-limit por usuario (anti-abuso)

1 participant