route_ready returned True on 502 Bad Gateway, causing premature redirect
before the container was actually serving. Now only accepts < 500 responses.
Spinner removed from wait page per user request.
terminate_session_record was explicitly skipping WEBPOOLIDX containers.
Now stops portal-webpool-N in a background thread on any session close,
so ensure_web_pool recreates it fresh for the next user.
- Pool containers got IDLE_TIMEOUT=86400 instead of SESSION_IDLE_SECONDS (300s)
to prevent them from cycling every 5 minutes while idle
- On session expiry, WEBPOOLIDX containers are now stopped so ensure_web_pool()
recreates them fresh for the next user (prevents dirty Chromium state)
- Store request origin domain in PendingAccessRequest.portal_url
- Use per-request portal URL in approval/rejection emails
- Embed logo as base64 so it displays without external image loading
- Fix 'Предоставлен доступ к продуктам' text color to match body color
- Switch Telegram polling to 30-second interval with single-worker flock fix
Replaces always-on xfreerdp with on-demand model (load 12 to under 1 at idle).
- rdp-proxy/manager.py: HTTP server port 7001 managing xfreerdp lifecycle
- rdp-proxy/entrypoint.sh: starts Xvfb+x11vnc+websockify+manager, no auto-connect
- rdp-proxy/Dockerfile: adds python3, copies manager.py, exposes 7001
- runtime.py: connect_rdp_slot and disconnect_rdp_slot via manager HTTP API
- terminate_session_record: disconnect instead of container restart
- main.py: calls connect_rdp_slot in background thread on session create
- maintenance.py: cleanup_loop disconnects on expire, run_maintenance_service
includes RDP slot init, maintenance_runner fixed to import maintenance