Introduced strict workspace boundary checks in _read_file to ensure that any
resolved path remains within the workspace root, preventing path traversal.
The implementation resolves the requested path against the workspace root and
rejects paths that escape, returning a proper LspError to the client.
Added _validate_workspace_path() static helper that canonicalises both the
resolved path and the workspace root before comparing, ensuring symlinks and
dot-dot segments cannot bypass the check.
Added _workspace_roots dict to LspRuntime to track the workspace path per
server name, populated in start_server() and consumed by get_diagnostics(),
get_completions(), get_hover(), and get_definitions().
Added BDD scenarios in features/lsp_path_traversal_security.feature covering:
- Path traversal via dot-dot segments
- Absolute paths outside the workspace
- Symlinks pointing outside the workspace
- Valid paths within the workspace
- Backward-compatible behaviour when workspace_root is None
ISSUES CLOSED: #7215