Allow remote dataset access - #71
Conversation
There was a problem hiding this comment.
Thanks for taking on remote dataset support. This addresses a real project need, but I’m requesting changes before merge.
There are two project-level requirements I need to settle as maintainer:
-
The existing local mounted-dataset workflow must remain available. This PR currently replaces the local dataset list with a remote URI form. Remote access should be additive rather than removing the primary local workflow.
-
The security model for arbitrary user-supplied URIs needs to be explicit. The viewer has no authentication, so allowing any browser user to submit s3://, filesystem, or other URIs could expose datasets accessible through the server’s credentials. Remote access needs a defined restriction/allowlist or a clearly trusted deployment model.
Please hold the implementation at this point while we agree those two design decisions. Once agreed, the revision should include:
- tests for the supported URI schemes and access policy;
- preservation of local dataset browsing.
The capability is valuable, but the current UI regression and unrestricted URI access mean this is not safe to merge yet.
|
Thanks for the mention! On the security model, there are two separate boundaries:
All users admitted to one viewer share that deployment’s storage permissions. Different access domains should use separate viewer deployments, namespaces, credentials, and hostname access policies. This is a trusted-deployment model rather than per-user authorization inside Lance Data Viewer. Deployments must not expose a credentialed viewer without external authentication. |
|
Your deployment model makes sense, and I agree that per-user authorization does not belong in this viewer. We will go with it. The mode has to be opt-in, so a default container never shows a location box. Someone who runs the documented docker run with a :ro mount must get exactly what they get today. Remote access turns on when the operator asks for it, which is what your Kubernetes setup describes anyway. There is a concrete reason for the guard beyond access control. lancedb.connect() creates the directory when the path does not exist. In 0.36.0 that is Path(uri).mkdir(parents=True, exist_ok=True) in db.py, and 0.33.0 does the same. So an unvalidated location box lets a typo write to the server filesystem. This project promises never to write to Lance data, so I want that closed in code rather than documented. What that means in practice:
|
|
One more thing before you rework this. The PR adds pylance as a runtime dependency, through lancedb[pylance] in requirements.txt and pylance==0.8.17 in pyproject.toml. Those two disagree with each other, and pylance is not pinned in any of the eight constraints
Every other dependency here is pinned per matrix entry, so an unpinned major across all eight images stands out. Worth settling before you spend time on it: this PR and #84 take different approaches to the same problem. Here you open one dataset by full URI with lance.dataset(), behind separate /remote/* endpoints. In #84 you point Rework against current main first, then merge. Most of the conflicting regions are in code the rework touches anyway, so they largely resolve themselves. |
|
This endpoint accepts arbitrary user-supplied URIs and passes them directly to lance.dataset(). Because local filesystem paths are also valid Lance URIs, a user can bypass the configured DATA_PATH//data boundary and read any I’m not suggesting removing remote storage support, but the trust boundary needs to be good. Possible approaches:
This is important because the viewer is unauthenticated by default, so arbitrary URI access could expose server-side data to anyone who can reach the UI. |
Closes #12
This PR adds remote storage support, so data viewer could load lance dataset from not only local filesystem.
The core change is pretty simple actually, since lance dataset already support remote access natively.
Initial UI

After a successful load

Followup item
AI usage disclaimer:
GPT-5.5 helped me make the code change, I deployed my own fork to k8s and verified it worked