Security
What the running app does. This page is not a certification, an audit report, or a promise about a control that is not in the code.
Hosting
The app is a hosted web service with a Postgres database. Request IP addresses come from the hosting platform. A forwarded-for list supplied by the browser is not trusted. A daily job clears old audit rows and checks watched carriers. It does not import a full FMCSA file.
Data we handle
- An account stores a name, an email address, a password hash, and the desk it belongs to. The password itself is not stored.
- Carrier rows are public FMCSA records loaded for a lookup or a watch. MileVet does not collect driver names from those files.
- A desk stores watchlist notes, submission notes, alert rows, and report views.
- API tokens are stored as a hash and a short prefix. The full token is shown once, when it is created.
- Share links are stored as a hash. The snapshot on a share link is the report at the time it was created.
- Email bodies kept in the app have links and one-time codes removed. Sign-in does not require an email provider to be configured.
Retention for audit events, report views, and email bodies is on the privacy page. The daily job deletes those rows. A page view does not.
Access control
- Desk pages require a session. The session cookie is httpOnly, SameSite=Lax, Secure in production, and expires after 14 days. It is a JWT. A password change invalidates older sessions.
- Queries for watches, alerts, tokens, and shares are scoped to the signed-in desk.
- A viewer cannot add a carrier to the watchlist.
- A share link expires, can be revoked, and does not grant a desk session.
- Passwords must be at least 12 characters and are rejected when they are on a common-password list. A missing account is checked the same way as a real one, so the response does not reveal whether the email exists.
Rate limits and lockouts
Sign-in, new accounts, search, lookups, PDF export, and the API are rate limited. An account locks after repeated failed passwords. A failure on another network does not lock the account. If the limit store cannot be reached, those actions fail closed instead of running without a limit.
Audit log
The audit log is the Activity page for a desk, plus sign-in failures stored without a desk. Rows record the action, a target such as a USDOT, an optional IP address, and a short detail. Actions in the code today include report views, PDF exports, share-link creates and opens, API reads, token issue and revoke, submission creates, decisions, and exports, alert-threshold changes, and failed sign-ins. Rows are deleted after 90 days.