# 2026-05-23 — MEDIUM Issue Fixes (Post-Audit Round 2)

## Summary
Fixed all 14+ MEDIUM issues identified in the full codebase audit.

## Changes

### Backend Core
- **WebSocket connection limits**: Added `MAX_CONNECTIONS=500` to ConnectionManager; rejects new connections when limit reached (memory DoS prevention)
- **WebSSH message size limits**: Added `MAX_MSG_SIZE=100KB` and `MAX_DATA_SIZE=10KB` validation before processing WebSocket messages
- **setting_repo SELECT-then-INSERT race**: Replaced TOCTOU pattern with MySQL `ON DUPLICATE KEY UPDATE` for atomic upsert
- **Migration atomicity**: Removed intermediate `session.commit()` calls — single commit at end for all-or-nothing migration
- **SyncLog/ScriptExecution return types**: Fixed `update_status()` return types from non-Optional to `Optional[SyncLog]` / `Optional[ScriptExecution]`

### Security Hardening
- **Nginx rate limiting**: Added `limit_req_zone` (10 req/s per IP, burst 20) for API endpoints
- **X-Forwarded-For IP extraction**: Added `_client_ip()` helper to auth.py that checks `X-Forwarded-For` header first, falls back to `request.client.host`
- **CDN SRI integrity hashes**: Added `integrity` + `crossorigin` attributes to all CDN script/style tags across all 12 HTML pages (tailwindcss, alpinejs, xterm, xterm-addon-fit)
- **Global 401 interceptor**: Added `window.fetch` override on all pages — auto-redirects to login on 401 responses

### Deployment
- **Supervisor stopasgroup**: Added `stopasgroup=true` to ensure SIGINT reaches entire process tree
- **health_monitor.sh hardening**: Added `set -euo pipefail`; wrapped FAIL_FILE read-modify-write in `flock` for atomicity
- **health_monitor.sh fail count**: All 3 fail-count access points now use `flock`-protected critical sections

### Code Quality
- **decrypt_value documentation**: Clarified backward-compat contract; added `try_decrypt_value()` for callers needing explicit success/failure signal
- **Dual DB session deprecation**: Marked `get_async_session()` as deprecated with docstring pointing to middleware-based `request.state.db` pattern

## Files Changed
39 files, 498 insertions, 210 deletions
