Remove the 'onFirstMessage' hack where backend sent VNC password as
first text WebSocket message and frontend passed the already-open WS
to noVNC's RFBClass. This caused RFB handshake failures because noVNC
couldn't properly manage a WebSocket it didn't create.
Changes:
- Backend: remove send_text(password) before proxy start
- Backend: improve proxy error logging from debug to info level
- Frontend (virtual_machines.html, instance_detail.html): pass WebSocket
URL string to RFBClass constructor - noVNC creates and manages its own
WebSocket connection, allowing proper RFB protocol handshake
- Migration 20: user_servers association table (User ↔ ProxmoxServer)
- API: GET/PUT /api/users/{id}/servers — assign servers to users with workspace-conflict validation
- API: GET /api/users/{id}/server-assignments — enriched server list (assigned + compatible flags)
- Non-admin server filter: intersection of assigned_servers and workspace servers
- Migration 21: dashboard:view = false for user role (new key format)
- Migration 22: proxmox.cluster.manage → cluster:manage for admin role
- API: GET/PUT /api/{server_id}/vm/{vmid}/owner — VM/LXC owner assignment (admin-only)
- Login: smart redirect based on user permissions after authentication
- Login: returnUrl param support for post-login redirect
- Roles API: user_count field per role in GET /api/roles
- node_uptime added to server detail API response
- Remove redundant PermissionChecker from GET /users HTML route
- Changed textContent to innerHTML for proper HTML icon rendering
- Fixed VNC modal titles in instance_detail.html, proxmox_vms.html, proxmox_server_detail.html
- Fixed command execution output icons in instance_detail.html
- Fixed settings and reinstall modal titles in proxmox_server_detail.html
- Added color styles to IPv4/IPv6 network interface icons