Summary
POST /shipments/:id/milestones/:index/proof accepts file uploads but has no rate limit. A malicious or buggy client could flood the IPFS node with repeated uploads. Throttling proof submissions to 5 per hour per user protects IPFS storage costs and prevents abuse.
Location
src/modules/milestones/milestones.controller.ts — add @Throttle decorator to the proof upload route
Expected Behaviour
- Add
@Throttle({ default: { limit: 5, ttl: 60 * 60 * 1000 } }) to the proof submission handler, matching the export endpoint pattern already used in ShipmentsController.
- Ensure the
ThrottlerGuard is configured to use userId from the JWT as the throttle key for authenticated routes (not IP address).
- Return HTTP 429 with a
Retry-After header when the limit is exceeded.
- Log rate limit violations at WARN level with the user's stellarAddress.
Acceptance Criteria
- The 6th proof upload within one hour returns 429
- The
Retry-After header indicates when the limit resets
- Rate limit resets after the TTL window
- The throttle key is per-user, not per-IP
Summary
POST /shipments/:id/milestones/:index/proofaccepts file uploads but has no rate limit. A malicious or buggy client could flood the IPFS node with repeated uploads. Throttling proof submissions to 5 per hour per user protects IPFS storage costs and prevents abuse.Location
src/modules/milestones/milestones.controller.ts— add@Throttledecorator to the proof upload routeExpected Behaviour
@Throttle({ default: { limit: 5, ttl: 60 * 60 * 1000 } })to the proof submission handler, matching the export endpoint pattern already used inShipmentsController.ThrottlerGuardis configured to useuserIdfrom the JWT as the throttle key for authenticated routes (not IP address).Retry-Afterheader when the limit is exceeded.Acceptance Criteria
Retry-Afterheader indicates when the limit resets