OneLake data plane
The onelake.dfs.fabric.microsoft.com surface: an ADLS-Gen2-shaped data
plane over the same store as the control plane,
accepting Storage-audience Entra tokens. Grounding: onelake-access-api.md
and onelake-api-parity.md in the pinned fabric-docs commit
(see 03-architecture.md, “Version grounding”).
The DFS surface (shipped, P3)
Section titled “The DFS surface (shipped, P3)”An ADLS-Gen2 / Blob subset (DFS endpoint), Storage-audience token. The
filesystem is the workspace (account name is always onelake), so listing
happens at the workspace level:
PUT /{workspace}/{item}.{type}/{path}?resource=file|directory— createPATCH …?action=append+?action=flush— writeGET /{workspace}/{item}.{type}/{path}— readGET /{workspace}?resource=filesystem&recursive=false[&directory={item}.{type}/Files]— listDELETE …
Managed-folder rules (onelake-api-parity.md — core fidelity, not
optional): ADLS/Blob APIs can never create, rename, or delete workspaces or
items — only HEAD is allowed at the workspace (container) and tenant
(account) level. An item’s top-level folder (/MyLakehouse.lakehouse) and its
first level (/Files, /Tables) are Fabric-managed: protected from
create/delete/rename; full CRUD only within them. Disallowed query parameters
(e.g. action=setAccessControl) reject the request; disallowed headers (e.g.
x-ms-owner) are ignored and echoed back in x-ms-rejected-headers.
Permission response headers are canned: x-ms-owner/x-ms-group =
$superuser, x-ms-permissions = ---------.
Enough for shortcut / trusted-workspace-access smoke tests. GUID and name-addressing both resolve to the same item.
Shortcuts (shipped)
Section titled “Shortcuts (shipped)”Wire shapes are REST-reference-only (/rest/api/fabric/core/onelake-shortcuts;
fabric-docs covers shortcut creation portal-side). A shortcut is a symlink in
OneLake: a named entry inside an item’s managed folders whose reads resolve
into another location. OneLake, ADLS Gen2, and Amazon S3 targets are supported;
external reads use the referenced Connection’s write-only credentials.
Dataverse remains unsupported and returns 501.
| Method + path | Notes |
|---|---|
POST /v1/workspaces/{wid}/items/{iid}/shortcuts | create → 201 |
GET /v1/workspaces/{wid}/items/{iid}/shortcuts | list sync |
GET /v1/workspaces/{wid}/items/{iid}/shortcuts/{path}/{name} | get sync |
DELETE /v1/workspaces/{wid}/items/{iid}/shortcuts/{path}/{name} | delete (removes the link, never the target) |
Create body (the OneLake target):
{ "path": "Files", "name": "linked-data", "target": { "oneLake": { "workspaceId": "…", "itemId": "…", "path": "Files/raw" } }}- Read-only resolution: shortcuts resolve on reads only (GET/HEAD). On
the DFS surface,
/{ws}/{item}/Files/linked-data/…resolves through to the target item’sFiles/raw/…when the direct path is absent. Resolution is authorized against the target workspace’s RBAC (the caller needs Contributor/ReadAll there — the trusted-workspace-access smoke path). - External resolution: ADLS Gen2 and Amazon S3 locations must be HTTP(S) URLs and name an existing Connection. Anonymous, Basic, Key, and SAS credentials are applied to read-through requests; failures surface as 502.
- Not in listings: the DFS list handler enumerates only real stored paths, so shortcut entries do not appear in directory listings.
- Writes don’t follow: PUT/PATCH/DELETE on a shortcut path write the source item, not the target — resolution is a read-side concern only.
- API shape: the shortcut endpoints return
{ path, name, target }only — there is noisShortcutfield. - Integrity: creating a shortcut to a missing item is rejected
(
400 TargetNotFound); deleting the target after creation leaves a dangling shortcut whose resolution 404s (matching real behavior); deleting the shortcut never touches target data. Self-referential cycles are rejected at create (400 InvalidTarget). - Storage: the
shortcutstable stores either OneLake ids or external target type/location/connection metadata. No data is copied.
The Blob surface (Delta commits)
Section titled “The Blob surface (Delta commits)”OneLake serves the same store over a Blob dialect
(onelake.blob.fabric.microsoft.com) alongside DFS (onelake-api-parity.md).
The Blob dialect is what Rust object_store — and therefore delta-rs —
speaks, so this is the surface delta writers actually hit. Two addressings
reach it:
- Host
onelake.blob.…→/{workspace}/{blob…} - Any host (endpoint override, azurite-style) →
/onelake/{workspace}/{blob…}— the/onelakeaccount prefix is stripped by the router; the account name is always the literalonelake.
Same managed-folder rules as DFS: PUT/DELETE at the workspace, item root, or its
first managed level are rejected (409); blobs live only within the managed
first level.
| Operation | Notes |
|---|---|
PUT …/{path} | Put Blob (whole-blob write) |
PUT …/{path}?comp=block&blockid=… | Put Block — stage an uncommitted block (base64 id) |
PUT …/{path}?comp=blocklist | Put Block List — commit staged blocks in order (XML body) |
PUT …/{path} + x-ms-copy-source | Copy Blob |
GET/HEAD …/{path} | read (Range supported) |
DELETE …/{path} | delete |
GET /{workspace}?comp=list | List Blobs (XML) — prefix, delimiter, marker, maxresults, startFrom |
Delta commit primitive. Put Blob with If-None-Match: * is a
put-if-absent: it succeeds only if the blob does not yet exist, else 409 BlobAlreadyExists. This is exactly how Delta Lake commits a new _delta_log
entry atomically — the conditional create is what makes concurrent writers race
safely for a version number. delta-rs / object_store rely on it; the emulator
honors it against the same store the DFS surface reads.
Listing offsets (startFrom). object_store implements list_with_offset
on Azure with a startFrom parameter, and it is inclusive — the opposite of
S3/GCP’s exclusive start-after, which object_store reconciles by dropping the
first entry when it equals the offset. Half-open semantics here would therefore
lose a blob, and ignoring the parameter is worse still: delta-rs’s
get_latest_version() receives a log segment starting at version 0 when it asked
for one starting at N, and the Delta kernel rejects it with Invalid table version: N. Plain writes keep working, so the breakage shows up only in the
commit-conflict paths — OPTIMIZE, VACUUM, MERGE. TestBlobListStartFrom
pins both the inclusivity and the precedence of marker over startFrom.