From cf262fbc676855175aabc2d263a62f66f0536d1e Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 4 Jun 2024 15:46:16 +0100 Subject: [PATCH] feat: use blob protocol capabilities (#92) Adjusts recommended capabilities to include blob protocol capabilities. Note: I didn't update the HTTP bridge docs as it requires more work. --- src/pages/docs/concepts/architecture-options.mdx | 4 ++-- src/pages/docs/concepts/ucan.md | 7 +++++-- src/pages/docs/concepts/ucans-and-web3storage.md | 8 ++++---- src/pages/docs/concepts/upload-vs-store.md | 4 ++-- src/pages/docs/how-to/ci.mdx | 6 +++--- src/pages/docs/how-to/upload.mdx | 6 +++--- 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/pages/docs/concepts/architecture-options.mdx b/src/pages/docs/concepts/architecture-options.mdx index 12bd560..ec2e53f 100644 --- a/src/pages/docs/concepts/architecture-options.mdx +++ b/src/pages/docs/concepts/architecture-options.mdx @@ -60,7 +60,7 @@ Your backend code can then re-delegate it's capabilities to your users. Your use When your user is ready to upload, they should request a delegation from your backend to upload to your Space. They must send their Agent DID so that the delegation is restricted to be used by only them. -In your backend, you can call [`client.createDelegation(...)`](https://github.com/web3-storage/w3up/blob/main/packages/w3up-client/README.md#createdelegation) passing in the Agent object from `client.agent()` in your end user's instance, and passing params to limit the scope of the delegation (e.g., `store/add`, `upload/add`, expiration time) +In your backend, you can call [`client.createDelegation(...)`](https://github.com/web3-storage/w3up/blob/main/packages/w3up-client/README.md#createdelegation) passing in the Agent object from `client.agent()` in your end user's instance, and passing params to limit the scope of the delegation (e.g., `space/blob/add`, `upload/add`, expiration time) You can serialize the delegation using `delegation.archive()` and send it to your user. @@ -98,7 +98,7 @@ async function backend(did) { // Create a delegation for a specific DID const audience = DID.parse(did) - const abilities = ['store/add', 'upload/add'] + const abilities = ['space/blob/add', 'space/index/add', 'filecoin/offer', 'upload/add'] const expiration = Math.floor(Date.now() / 1000) + (60 * 60 * 24) // 24 hours from now const delegation = await client.createDelegation(audience, abilities, { expiration }) diff --git a/src/pages/docs/concepts/ucan.md b/src/pages/docs/concepts/ucan.md index ed42fb3..a4ce5fc 100644 --- a/src/pages/docs/concepts/ucan.md +++ b/src/pages/docs/concepts/ucan.md @@ -104,7 +104,7 @@ async function delegationRequestHandler (request) { // we're issuing the delegation to, as well as a list of // "ability" strings. // Here, we're passing in the abilities needed to upload to the space: - // 'space/info', 'store/add', and 'upload/add'. + // 'space/blob/add', 'space/index/add', 'filecoin/offer', and 'upload/add'. // // With these capabilities, the user will be able to upload to the space, // but they won't be able to list existing uploads or perform any "management" @@ -113,7 +113,10 @@ async function delegationRequestHandler (request) { // // See the capabilities spec for more about capabilities: // https://github.com/web3-storage/w3protocol/blob/main/spec/capabilities.md - const delegation = await client.createDelegation(userDID, ['store/add', 'upload/add']) + const delegation = await client.createDelegation( + userDID, + ['space/blob/add', 'space/index/add', 'filecoin/offer', 'upload/add'] + ) // The delegation object is a binary "blob" that encodes the UCAN // delegation into the CAR format. diff --git a/src/pages/docs/concepts/ucans-and-web3storage.md b/src/pages/docs/concepts/ucans-and-web3storage.md index 44ae203..174ddef 100644 --- a/src/pages/docs/concepts/ucans-and-web3storage.md +++ b/src/pages/docs/concepts/ucans-and-web3storage.md @@ -14,13 +14,13 @@ UCAN-based APIs are centered around _capabilities_, which are comprised of an _a When you upload data to w3up, your uploads are linked to a unique _Space_ that acts as a "namespace" for the data you upload. Each Space corresponds to a _DID_, or [Decentralized Identity Document](https://www.w3.org/TR/did-core/). In web3.storage's implementation of w3up, these Space DIDs generally use the key DID method, of the form did:key:publicKey with a corresponding private signing key. -When creating a Space, it generates this private key and did:key for you locally. To use web3.storage, you then register a Space by associating it with your email address. From there, when invoking storage capabilities with web3.storage, the Space did:key is the "resource" portion of the capability, while the ability is an action like store/add or store/remove. (A Space registered with web3.storage is imperfectly analogous to an "account" with web3.storage.) +When creating a Space, it generates this private key and did:key for you locally. To use web3.storage, you then register a Space by associating it with your email address. From there, when invoking storage capabilities with web3.storage, the Space did:key is the "resource" portion of the capability, while the ability is an action like space/blob/add or space/blob/remove. (A Space registered with web3.storage is imperfectly analogous to an "account" with web3.storage.) Under the hood in the email registration process, your Space delegates the capabilities needed to use w3up to your email address, and this delegation is stored by web3.storage. If you need access to your Space in the future from any device, web3.storage allows you to reclaim those capabilities the same way you would reset a password in other services - using an email verification process. This means you don't need to store or manage Space private keys to use w3up - just create a new space, register it with w3up and use it from as many devices as you like. More on this "sign in" process is detailed in the next section on Agents. ### Agent -To invoke a capability like store/add on a Space using the client or CLI, the client must have an _Agent_. Like a Space, an Agent corresponds to a did:key whose private key is generated locally. An Agent is useful once the client or CLI has a UCAN delegation where a registered Space(s) delegates the Agent its capabilities. (An imperfect analogy is Agent to login session.) +To invoke a capability like space/blob/add on a Space using the client or CLI, the client must have an _Agent_. Like a Space, an Agent corresponds to a did:key whose private key is generated locally. An Agent is useful once the client or CLI has a UCAN delegation where a registered Space(s) delegates the Agent its capabilities. (An imperfect analogy is Agent to login session.) The delegation from a Space to your Agent that w3up-client needs can be passed either by verifying the email address the Space is registered to and claiming the UCAN delegation (authorize(email) then capability.access.claim) or directly if you have the UCAN delegation available locally (addSpace(delegation)). @@ -51,7 +51,7 @@ async function backend(did) { // Create a delegation for a specific DID const audience = DID.parse(did) - const abilities = ['store/add', 'upload/add'] + const abilities = ['space/blob/add', 'space/index/add', 'filecoin/offer', 'upload/add'] const expiration = Math.floor(Date.now() / 1000) + (60 * 60 * 24) // 24 hours from now const delegation = await client.createDelegation(audience, abilities, { expiration }) @@ -74,7 +74,7 @@ async function parseProof(data) { When the `backend` function is called in the developer's backend: - It's passed the DID of the user's Agent - Backend client initializes with an Agent that has permission to the developer's Space -- It then generates a UCAN delegated to the user Agent DID passed in with only the `store/add` and `upload/add` abilities (to give the user ability to upload) and set to expire in 24 hours +- It then generates a UCAN delegated to the user Agent DID passed in with only the `space/blob/add`, `space/index/add`, `filecoin/offer` and `upload/add` abilities (to give the user ability to upload) and set to expire in 24 hours **Frontend** diff --git a/src/pages/docs/concepts/upload-vs-store.md b/src/pages/docs/concepts/upload-vs-store.md index 278c5a6..e8762f0 100644 --- a/src/pages/docs/concepts/upload-vs-store.md +++ b/src/pages/docs/concepts/upload-vs-store.md @@ -47,9 +47,9 @@ Let's break it down. In the CLI example above where we called `w3 up file`, we s The CLI and client first take the upload and converts it into an DAG (directed acyclic graph). This is what IPFS uses to generate the content CID - each node in the graph has its own CID, with the graph's leafs containing the upload's data, and the root node of the graph the content CID of the entire graph. However, to send the data to web3.storage, the content has to be in a different form. web3.storage achieves this by converting the graph into a set of CAR file shards. -Each CAR shard has a CID associated with the data itself (i.e., as it sits on disk serialized, with a header for instructions on how the blocks within the serialized data should be arranged, etc.). The CLI and client send each of these shards one-by-one to web3.storage by invoking the `store/add` UCAN capability under the hood (e.g., `w3 can store add`)! +Each CAR shard has a CID associated with the data itself (i.e., as it sits on disk serialized, with a header for instructions on how the blocks within the serialized data should be arranged, etc.). The CLI and client send each of these shards one-by-one to web3.storage by invoking the `space/blob/add` UCAN capability under the hood (e.g., `w3 can blob add`)! -However, from web3.storage's perspective, it doesn't necessarily know whether the set of CAR shards it was sent from the series of `store/add`s corresponds to a single content CID that the user cares about, multiple content CIDs, or none at all (e.g., the CAR files sent represent an incomplete graph). As a result, `upload/add` allows the user to explicitly register a content CID with a set of shard CIDs. This is primarily done for the user's sake - it makes it easier to track which content CIDs (what they're using to fetch data from the IPFS network) correspond to which shard CIDs (what is physically being stored with web3.storage). +However, from web3.storage's perspective, it doesn't necessarily know whether the set of CAR shards it was sent from the series of `space/blob/add`s corresponds to a single content CID that the user cares about, multiple content CIDs, or none at all (e.g., the CAR files sent represent an incomplete graph). As a result, `upload/add` allows the user to explicitly register a content CID with a set of shard CIDs. This is primarily done for the user's sake - it makes it easier to track which content CIDs (what they're using to fetch data from the IPFS network) correspond to which shard CIDs (what is physically being stored with web3.storage). In cases where the user is uploading a whole file or directory like in the example above, it's safe to know that the series of CAR shards uploaded by the user correspond to the file's content CID that it cares about. That's why the higher-level `w3 up` method is appropriate to use, and should represent the vast majority of upload use cases by web3.storage users. diff --git a/src/pages/docs/how-to/ci.mdx b/src/pages/docs/how-to/ci.mdx index f5ea3c4..68ade5d 100644 --- a/src/pages/docs/how-to/ci.mdx +++ b/src/pages/docs/how-to/ci.mdx @@ -33,7 +33,7 @@ $ w3 key create --json > ci-key.json $ AUDIENCE=$(jq -r .did ci-key.json) # Create a signed proof that you delegate capabilties to that key. -$ w3 delegation create $AUDIENCE -c store/add -c upload/add --base64 +$ w3 delegation create $AUDIENCE -c space/blob/add -c space/index/add -c filecoin/offer -c upload/add --base64 mAYIEAP8OEaJlcm9vdHOAZ3ZlcnNpb24BwwUBcRIg+oHTbzShh1WzBo9ISkonCW+KAcy/+zW8Zb... # Pass the output to `w3 space add` in ci @@ -90,7 +90,7 @@ The `did` from the command above is the public decentalised identifier for that On your local machine, use [w3cli][] to delegate capabilties to upload to our space to the public DID for the signing key we created. -Our CI environment doesn't need to list our uploads or change our billing plan so we only delegate the `store/add` and `upload/add` capabilities to it. +Our CI environment doesn't need to list our uploads or change our billing plan so we only delegate the `space/blob/add`, `space/index/add`, `filecoin/offer` and `upload/add` capabilities to it. Pass the `did` for the signing key as the audience parameter. We are delegating capabilities to that key. @@ -98,7 +98,7 @@ Pass the `did` for the signing key as the audience parameter. We are delegating $ AUDIENCE=did:key:z6Mk... # Delegate capabilities to the `did` we created above. -$ w3 delegation create $AUDIENCE -c 'store/add' -c 'upload/add' --base64 +$ w3 delegation create $AUDIENCE -c space/blob/add -c space/index/add -c filecoin/offer -c upload/add --base64 mAYIEAP8OEaJlcm9vdHOAZ3ZlcnNpb24BwwUBcRIg+oHTbzShh1WzBo9ISkonCW+KAcy/+zW8Zb... ``` diff --git a/src/pages/docs/how-to/upload.mdx b/src/pages/docs/how-to/upload.mdx index 8d2c78a..ebbd595 100644 --- a/src/pages/docs/how-to/upload.mdx +++ b/src/pages/docs/how-to/upload.mdx @@ -129,8 +129,8 @@ w3 key create # access to. # # If you want to limit permissions being passed to the Agent, you can specify -# permissions to give, e.g., `--can 'store/add' --can 'upload/add'` limits to -# just being able to upload. +# permissions to give, e.g., `--can space/blob/add --can space/index/add --can +# filecoin/offer --can upload/add` limits to just being able to upload. w3 delegation create | base64 # ❗️ Store the output in environment variable PROOF @@ -246,7 +246,7 @@ async function backend(did) { // Create a delegation for a specific DID const audience = DID.parse(did) - const abilities = ['store/add', 'upload/add'] + const abilities = ['space/blob/add', 'space/index/add', 'filecoin/offer', 'upload/add'] const expiration = Math.floor(Date.now() / 1000) + (60 * 60 * 24) // 24 hours from now const delegation = await client.createDelegation(audience, abilities, { expiration })