Files
Alexandre Possebom 4bc7614292 fix: resolve confirmed bugs from bug hunt
Fixes verified by the 3-agent adversarial bug hunt (hunter, skeptic,
referee). Grouped by area:

Security
- routes: webhook internal-network check now reads the real client IP
  (rightmost X-Forwarded-For hop, same as the rate limiter) so the
  unauthenticated /api/plate and /api/unifi are no longer reachable
  from the internet through Traefik
- config: mask the DB password in the startup log
- frontend: remove the dead /sign-up template that logged the
  plaintext password to the console

Correctness and data integrity
- passage_ingest: serialize ingestion per plate to close the debounce
  check-then-act race (duplicate passages and duplicate alert fan-out)
- api_vehicles: delete now removes the plate's images from disk (were
  left orphaned) and the delete dialog warns about history/image loss
- passagem_repository: cast plate params to bpchar[] to keep the index
  on the hot passages queries
- camera_repository: reject out-of-range ids instead of truncating i64
  to i32, which could act on the wrong camera
- api_vehicles: reject create with both a driver and a company
- api_users: block an admin from removing their own admin flag
- api_dashboard: clamp available spots to [0, total] and propagate DB
  errors instead of reporting capacity as 0
- api_alerts: map FK violation (23503) to 404 instead of an opaque 500
- api_profile: validate that the email contains '@'
- api_drivers: measure name length by chars, not bytes
- dahua: fail list_plates on firmware truncation so reconcile flags the
  camera instead of diffing a partial list
- image: passage thumbnails now honor the per-camera crop_percent
- dashboard: keep the live feed bounded instead of growing forever

Regenerated .sqlx for the changed queries and routeTree.gen.ts.
2026-07-16 10:23:32 -03:00
..