fix: panic recovery, rate limiting, transaction error handling, pagination

Hardening pass over the API surface. No route's auth requirements change.

Resilience:
- Add recover middleware. There was none, so an unhandled panic in any
  handler propagated out of the process instead of becoming a 500.
- Add a centralized ErrorHandler so errors and recovered panics return the
  same {success,message} envelope as the utils helpers, not Fiber's default
  plain-text body. 5xx responses are logged with method and path.

Rate limiting:
- Global 300/min per IP as an abuse backstop, exempting health/readiness
  probes and websocket upgrades.
- 10/min shared across every credential endpoint (customer/miler/admin/hub
  login, verify-pin, reset-pin, email OTP). PINs are 4 digits, so the whole
  keyspace was previously walkable in seconds. One shared limiter instance
  means rotating between endpoints doesn't reset the budget.
- Add TRUSTED_PROXIES config. Limits key on c.IP(), which behind a TLS
  terminator is the proxy, collapsing every client into one bucket. When set,
  X-Forwarded-For is honoured only from those proxies so the header can't be
  spoofed to dodge the limit. Logs a warning when unset.

Transactions:
- Check the error on all 51 previously-unchecked tx.Save/Create/Delete/
  Model(...).Update/Commit calls across 6 controllers. A failed write inside
  a transaction was silently ignored and the request still reported success;
  an unchecked Commit could fail with the caller told everything worked.
  Each site now rolls back and returns a specific message.

Pagination:
- Add utils.ParsePage/Paginated, reusing the pageno/pagesize convention
  GetAdminBookings already established. Default 500, hard cap 1000.
- Apply to the previously unbounded consignments, tripsheets, exceptions,
  app-users and clients endpoints. Defaults are high so existing consoles
  that don't paginate keep working; the cap only stops a growing table from
  being loaded wholesale. total is now a real COUNT, not len(data).
- GetClients also loaded the entire auth table to join in memory; it now
  fetches only the current page's rows.

Tests (first in the repo):
- Extract the hyperlocal pincode rule out of BookingPickupComplete into
  isHyperlocal so it is testable, covering the short/empty pincode fallback.
- Cover calculateVolumetricWeight and the ParsePage clamping rules.

Repo hygiene:
- Tag scratch/*.go with //go:build ignore. Each declared its own main(), so
  `go build ./...` failed on redeclaration; it now passes repo-wide.
- Untrack scratch/node_modules (216 files) and ignore node_modules, test
  artifacts, and the `doormile` binary `go build .` emits.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Suriya
2026-07-27 12:13:39 +05:30
parent a2b9268189
commit 2c26cbe4ba
240 changed files with 753 additions and 76753 deletions

4
go.sum
View File

@@ -110,6 +110,8 @@ github.com/nats-io/nkeys v0.4.5 h1:Zdz2BUlFm4fJlierwvGK+yl20IAKUm7eV6AAZXEhkPk=
github.com/nats-io/nkeys v0.4.5/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c h1:dAMKvw0MlJT1GshSTtih8C2gDs04w8dReiOGXrGLNoY=
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -128,6 +130,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tinylib/msgp v1.2.5 h1:WeQg1whrXRFiZusidTQqzETkRpGjFjcIhW6uqWH09po=
github.com/tinylib/msgp v1.2.5/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=