- sign-in pages load only what they use (include_login_header.php, ajax_core.js)
- every library, font and data file served from assets/vendor with pinned
versions (VERSIONS.json); no CDN at runtime
- Content-Security-Policy on app, sign-in and landing pages
- remove httpbin Dropzone target and source-map references
- users, SMTP and batch-lock endpoints are owner/admin only
- engines answer 400/403/404/409/500 instead of 200 with an error body;
database errors no longer leak to the client
- OTP attempt limits, constant-time compare, random reference codes
- DB-backed rate limits (429) on sign-in, OTP, reset, register, onboarding
- one generic sign-in failure message; reset request no longer reveals accounts
- no password kept in the session; real status codes on failures
Stock Transfer list showed 0.00 (read in instead of out); stock-out/transfer forms show the location quantity; dates display as YYYY-MM-DD HH:mm:ss. Demo seeds map product accounts and use product names and supplier batches.