Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@
"pages": [
"reference/networks-and-endpoints",
"reference/authentication-matrix",
"reference/vfs-content-addressing",
"reference/product-and-sdk-map",
"reference/glossary"
]
Expand Down
126 changes: 126 additions & 0 deletions reference/vfs-content-addressing.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
title: "VFS content addressing (IPFS CIDs)"

Check warning on line 2 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L2

Did you really mean 'CIDs'?
description: "How the IXO Virtual Filesystem computes IPFS CIDs per file, the fetch and list-by-CID endpoints, MCP tools, x-vfs-cid header, and CID-scoped UCANs."

Check warning on line 3 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L3

Did you really mean 'CIDs'?

Check warning on line 3 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L3

Did you really mean 'UCANs'?
---

The IXO Virtual Filesystem (VFS) stamps every file with an **IPFS-compatible CID** computed over its plaintext. Nothing is uploaded to IPFS — the CID is a content-addressed identity and integrity check that a downloader can re-derive to verify the bytes. The bytes themselves stay encrypted in R2.

Check warning on line 6 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L6

Did you really mean 'plaintext'?

Check warning on line 6 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L6

Did you really mean 'downloader'?

Use this page when you need to:

- Address a VFS file by content (fetch or list by CID) instead of by path.
- Cross-reference a file against another IXO service that speaks the same CID (for example `ixo-cellnode` or a Storacha upload).

Check warning on line 11 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L11

Did you really mean 'Storacha'?
- Grant an agent access to a specific set of blobs — and nothing else — via a CID-scoped UCAN.

## The CID contract

The VFS uses the exact UnixFS encoder settings that Storacha / web3.storage (and `ixo-cellnode`) use, so the CID a VFS file carries is **byte-identical** to the CID you would get by running `ipfs add` (via Storacha) on the same plaintext.

Check warning on line 16 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L16

Did you really mean 'Storacha'?

Check warning on line 16 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L16

Did you really mean 'Storacha'?

Check warning on line 16 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L16

Did you really mean 'plaintext'?

| Setting | Value |
| --- | --- |
| CID version | CIDv1 |
| Leaf encoder | `raw` |
| Chunk size | 1 MiB (1 048 576 bytes) |
| Layout | Balanced, fan-out 1024 |
| Hash | sha2-256 |

Consequences:

- A file **≤ 1 MiB** is a single raw leaf and its CID starts with `bafkrei…`.
- A larger file is a dag-pb UnixFS DAG and its CID starts with `bafybei…`.
- The CID is computed over the **plaintext**, in a single streaming pass alongside the encryptor, so it works on files larger than Worker memory.

Check warning on line 30 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L30

Did you really mean 'plaintext'?

Check warning on line 30 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L30

Did you really mean 'encryptor'?
- The CID is type-agnostic — text, binary, images all hash the same way.

## The `x-vfs-cid` response header

Every content-returning route sets `x-vfs-cid` to the CID stored for the file. A client that keeps the plaintext can re-derive the same CID locally to verify the download:

Check warning on line 35 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L35

Did you really mean 'plaintext'?

```http
GET /api/fs/files/:id/content
Authorization: Bearer <UCAN>

HTTP/1.1 200 OK
content-type: text/markdown
x-vfs-cid: bafkreib...
x-vfs-content-hash: 3f9c...
x-vfs-version: 4
```

`GET /api/fs/cid/:cid` sets the same header on its response.

## Fetch and list by CID (REST)

Two content-addressed routes complement the path-oriented API. Authority comes from the namespace: the auth middleware has already proved the caller owns the address (or controls the entity), so these routes only ever see the caller's own files, and a CID that lives in another namespace returns **404** (never confirmed to exist).

Check warning on line 52 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L52

Did you really mean 'namespace'?

Check warning on line 52 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L52

Did you really mean 'namespace'?

| Method | Path | Returns | Ability |
| --- | --- | --- | --- |
| `GET` | `/api/fs/cids?limit=&offset=` | List of files addressable by CID in the caller's namespace (`cid`, `id`, `path`, `name`, `size`, `mimeType`) | `fs/read` |

Check warning on line 56 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L56

Did you really mean 'namespace'?
| `GET` | `/api/fs/cid/:cid` | Decrypted bytes for that CID in the caller's namespace (`x-vfs-cid` header; 404 if no accessible match) | `fs/read` |

Check warning on line 57 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L57

Did you really mean 'namespace'?

Path scope still applies: a path-scoped UCAN can only fetch or list CIDs whose file lives inside its subtree, even if an identical-content file exists elsewhere in the namespace.

Check warning on line 59 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L59

Did you really mean 'CIDs'?

Check warning on line 59 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L59

Did you really mean 'subtree'?

Check warning on line 59 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L59

Did you really mean 'namespace'?

```bash
# List content in this namespace
curl -H "Authorization: Bearer $UCAN" \
"https://vfs.example.com/api/fs/cids?limit=50"

# Fetch bytes by CID
curl -H "Authorization: Bearer $UCAN" \
"https://vfs.example.com/api/fs/cid/bafkreib..." \
--output file.bin
```

## MCP tools

Agents connected via the VFS MCP server get two content-addressed tools alongside the path-oriented ones. Both honour path scope in addition to CID scope.

| Tool | What it does | Ability |
| --- | --- | --- |
| `vfs_list_cids` | List files addressable by CID; returns `cid path (size)` per line. | `fs/read` |
| `vfs_read_cid` | Numbered-line read of a text file by its CID, with `offset` / `limit` paging (same shape as `vfs_read`). | `fs/read` |

`vfs_write` also reports the freshly computed CID for the newly written version in its result, so an agent can immediately hand the CID to a downstream tool.

## CID-scoped UCANs (`nb.cids` caveat)

Check warning on line 83 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L83

Did you really mean 'UCANs'?

A UCAN can be attenuated to a **specific set of CIDs** by adding an `nb.cids` caveat to a capability. This is IXO's "least privilege for blobs": share exactly the files you mean to share and nothing else — the token cannot browse, search, or mutate the tree.

Check warning on line 85 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L85

Did you really mean 'CIDs'?

Check warning on line 85 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L85

Did you really mean 'IXO's'?

### Semantics

- **Confined surface.** A CID-scoped token may use *only* the content-addressed surface:
- REST: `GET /api/fs/cid/:cid` and `GET /api/fs/cids`.
- MCP: `vfs_read_cid` and `vfs_list_cids` are the only tools the session advertises.
- **Restricted set.** Requests are allowed only for CIDs in the granted set. Anything else returns `403`.

Check warning on line 92 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L92

Did you really mean 'CIDs'?
- **Attenuates down the chain.** The effective scope is the **intersection** of every `nb.cids` set found in the delegation chain (leaf + all proofs). A delegate can only ever **shrink** the set, never widen it — a CID absent from an ancestor's set drops out of the intersection and is denied.
- **Composes with other scope caveats.** `nb.cids` intersects with path scope and namespace scope; **the most restrictive wins**. A CID-scoped token that also carries a path scope can only reach CIDs whose file lives inside the granted subtree.

Check warning on line 94 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L94

Did you really mean 'namespace'?

Check warning on line 94 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L94

Did you really mean 'CIDs'?

Check warning on line 94 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L94

Did you really mean 'subtree'?
- **Namespace isolation is preserved.** A CID-scoped token still can't cross namespaces — a granted CID that doesn't exist in the caller's namespace resolves to `404`.

Check warning on line 95 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L95

Did you really mean 'Namespace'?

Check warning on line 95 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L95

Did you really mean 'namespaces'?

Check warning on line 95 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L95

Did you really mean 'namespace'?
- **Explicit empty list.** `nb.cids: []` is a valid but useless grant: no CIDs are reachable.

Check warning on line 96 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L96

Did you really mean 'CIDs'?
- **Absence means unrestricted.** If no capability in the chain carries `nb.cids`, the token is not CID-scoped at all.

### Example capability shape

```json
{
"can": "fs/read",
"with": "vfs://user:did:ixo:...",
"nb": {
"cids": [
"bafkreib...",
"bafybei..."
]
}
}
```

Delegate that token further and the child can only list a **subset** of those two CIDs — never a third one.

Check warning on line 114 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L114

Did you really mean 'CIDs'?

## When to use content addressing

- **Verifiable delivery.** Pair `/cid/:cid` with a client-side re-hash to prove the bytes match a known CID before you trust them.
- **Cross-service references.** Store a CID in another system (a claim, an on-chain entity record, a Storacha pin) and resolve it back to the VFS file later, regardless of where it lives in the tree.

Check warning on line 119 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L119

Did you really mean 'Storacha'?
- **Precise sharing.** Hand an agent a CID-scoped UCAN when it needs to read a fixed set of blobs (evaluator inputs, a specific policy document) and should not see anything else — even if the token is later delegated onward, the set can only shrink.
- **Interop with the wider IXO stack.** The CID matches what `ixo-cellnode` and a direct Storacha / web3.storage upload would produce for the same plaintext, so the same identifier can flow across those systems.

Check warning on line 121 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L121

Did you really mean 'Interop'?

Check warning on line 121 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L121

Did you really mean 'Storacha'?

Check warning on line 121 in reference/vfs-content-addressing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (ixoworld) - vale-spellcheck

reference/vfs-content-addressing.mdx#L121

Did you really mean 'plaintext'?

## Related

- [Authentication matrix](/reference/authentication-matrix) — where the VFS `Bearer <UCAN>` pattern fits.
- [MCP servers](/mcp/model-context-protocol) — how agents connect to IXO MCP surfaces.
Loading