Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: introduce http/put capability #116

Merged
merged 8 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
140 changes: 128 additions & 12 deletions w3-blob.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ Added("🧾 { ok: { claim 🚦 } }")

Allocate("⏭️ /service/blob/allocate 🤖")

Put("⏭️ /http/put 🤖🔑")

Accept("⏭️ /service/blob/accept 🤖")

Accepted("🧾 { ok: { claim 🎫 } }")
Expand All @@ -71,7 +73,10 @@ Claim("🎫 /assert/location 🤖👩‍💻")
Add --o Added
Added -.-> Allocate
Added -.-> Accept
Added -.-> Put
Allocate --> Accept

Put --> Accept
Accept --o Accepted
Accepted -- claim --> Claim
Added -- claim --> Accept
Expand Down Expand Up @@ -150,8 +155,28 @@ Shows an example receipt for the above `/space/content/add/blob` capability invo
}
}
},
// 2. System will attempt to accept received content
// if matches blob multihash and size.
// 2. System requests user agent (or anyone really) to upload the content
// corresponding to the blob
// via HTTP PUT to given location.
{ // "/": "bafy...upload",
Gozala marked this conversation as resolved.
Show resolved Hide resolved
"cmd": "/http/put",
"sub": "did:key:zMh...der", // <-- Ed299.. derived key from content multihash
"args": {
"content": { "/": { "bytes": "mEi...sfKg" } },
"address": {
"url": "https://r2.cloudflare.com/ipfs/bafy...",
"headers": {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I now realize that this is not great :/ We can iterate after, but in the world of write to anywhere where in allocate we could look async for write targets to write, we now need to know these right away. I wonder what would be the downside of just passing the content, as service will always need to validate it

}
Gozala marked this conversation as resolved.
Show resolved Hide resolved
},
"meta": {
// archive of the principal keys
"keys": {
"did:key:zMh...der": { "/": "mEi...sfKg" }
}
}
},
Gozala marked this conversation as resolved.
Show resolved Hide resolved
// 3. System will attempt to accept uploaded content that matches blob
// multihash and size.
{ // "/": "bafy...accept",
"cmd": "/service/blob/accept",
"sub": "did:web:web3.storage",
Expand All @@ -164,7 +189,8 @@ Shows an example receipt for the above `/space/content/add/blob` capability invo
},
exp: 1711122994101,
// This task is blocked on allocation
_: { "await/ok": { "/": "bafy...alloc" } }
_allocate: { "await/ok": { "/": "bafy...alloc" } },
_put: { "await/ok", { "/": "bafy...put" } }
}
}
]
Expand Down Expand Up @@ -213,6 +239,7 @@ type AddBlobReceipt = {
out: Result<AddBlobOk, AddBlobError>
next: [
AllocateBlob,
PutBlob,
AcceptBlob,
]
}
Expand Down Expand Up @@ -246,6 +273,7 @@ Task linked from the `claim` of the success value MUST be present in the receipt
Successful invocation MUST start a workflow consisting of following tasks, that MUST be set in receipt effects (`next` field) in the following order.

1. [Allocate Blob]
1. [Put Blob]
1. [Accept Blob]

## Allocate Blob
Expand Down Expand Up @@ -325,11 +353,77 @@ It is RECOMMENDED that issued `BlobAddress` only accept `PUT` payload that match

Allocation MUST have no effects.

## Put Blob

Any agent MAY perform `/http/put` capability invocation on behalf of the subject. [Add blob] capability provider MUST add `/http/put` effect and capture private key of the `subject` in the `meta` field so that any agent could perform it.

An agent that invoked [add blob] capability is expected to perform this task and issue receipt on completion.

### Put Blob Capability

#### Put Blob Capability Schema

> ℹ️ In the UCAN 0.9 `meta` is unknown as `fct` field

```ts
type BlobPut = {
cmd: "/http/put"
sub: DID
args: {
content: Multihash
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make this a Blob instead? when we receive a http/put having the blob allows us to invoke blob/accept right away. Otherwise, we need to look at state to find it out

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
content: Multihash
body: Blob

Something like this you mean ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, body or Blob is good for me

address: BlobAddress
Gozala marked this conversation as resolved.
Show resolved Hide resolved
Gozala marked this conversation as resolved.
Show resolved Hide resolved
}
meta: {
keys: {[key: DID]: bytes}
}
}
```

### Put Blob Subject

The subject field SHOULD be [`did:key`] corresponding to the [Ed25519] private key that is first 32 bytes of the blob [multihash].

### Put Blob Metadata

Metadata MUST contain `keys` field with an object value that contains [`did:key`] subject as key and corresponding private key as bytes as a value.

### Put Blob Address

Destination address `url` and required `headers` MUST be specified in the arguments.

### Put Blob Receipt

Receipt is signal to the service to proceed with [accept blob]. Service implementation that does not require signal from the client it MAY issue receipt when content is uploaded.

ℹ️ Client MAY use [UCAN conclusion] capability to deliver receipt to the awaiting service.

#### Put Blob Receipt Schema

```ts
type BlobPutReceipt = {
ran: Link<BlobPut>
out: Result<BlobPutOk, BlobPutError>
next: []
}

type BlobPutOk = {}

type AddPutError = {
message: string
}
```

#### Blob Put Effects

Receipt MUST not have any effects.

## Accept Blob

Authorized agent MAY invoke `/service/blob/accept` capability on the [provider] subject. Invocation MUST either succeed when content is delivered on allocated `address` or fail if no content is allocation expires without content being delivered.
Authorized agent MAY invoke `/service/blob/accept` capability on the [provider] subject. Invocation MUST either succeed when content is delivered on allocated `address` or fail if either allocation failed or expired before content was delivered.

ℹ️ Implementation that is unable to enforce to reject HTTP PUT request that do not match blob [multihash] or `size` SHOULD enforce that invariant in this invocation by failing task if no valid content has been delivered.
Invocation MUST block until content is delivered. Implementation MAY resume when content is sent to the allocated address or await until client signals that content has been delivered using [put blob receipt].

ℹ️ Implementation that is unable to reject HTTP PUT request for the payload that does not match blob [multihash] or `size` SHOULD enforce the invariant in this invocation by failing task if no valid content has been delivered.

### Accept Blob Capability

Expand Down Expand Up @@ -375,13 +469,36 @@ Receipt MUST not have any effects.
Location claim represents commitment from the issuer to the audience that
content matching the `content` [multihash] can be read via HTTP [range request]

### Location Claim Delegation Example

```js
{
"iss": "did:web:web3.storage",
"aud": "did:key:zAlice",

"cmd": "/assert/location",
"sub": "did:web:web3.storage",
"pol": [
// multihash must match be for the blob uploaded
["==", ".content", { "/": { "bytes": "mEi...sfKg" } }],
Gozala marked this conversation as resolved.
Show resolved Hide resolved
// must be available from this url
["==", ".url", "https://w3s.link/ipfs/bafk...7fi"],
// from this range
["==", ".range[0]", 0],
["==", ".range[1]", 2_097_152],
],
// does not expire
"exp": null
}
```

### Location Claim Capability

#### Location Claim Capability Schema

```ts
type LocationClaim = {
cmd: "assert/location"
cmd: "/assert/location"
sub: ProviderDID
args: {
content: Multihash
Expand All @@ -393,12 +510,6 @@ type LocationClaim = {

# Coordination

## Accept Content

[Accept Blob] invocation will block until content is delivered, however some implementations may not be able to observe when content was received. Those implementations can await for subsequent [Add Blob] invocations and re-check whether content has been received.

Note that implementation MUST be idempotent and same receipts MUST be returned to the caller, yet pending tasks could be updated.

## Publishing Blob

Blob can be published by authorizing read interface (e.g. IPFS gateway) by delegating it [Location Claim] that has been obtained from the provider.
Expand All @@ -413,8 +524,13 @@ Blob can be published by authorizing read interface (e.g. IPFS gateway) by deleg
[await/ok]:https://github.com/ucan-wg/invocation?tab=readme-ov-file#await
[location claim]:#location-claim
[Add Blob]:#add-blob
[Put Blob]:#put-blob
[put blob receipt]:#put-blob-receipt
[Allocate Blob]:#allocate-blob
[Accept Blob]:#accept-blob
[DID]:https://www.w3.org/TR/did-core/
[Link]:https://ipld.io/docs/schemas/features/links/
[range request]:https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests
[`did:key`]:https://w3c-ccg.github.io/did-method-key/
[Ed25519]:https://en.wikipedia.org/wiki/EdDSA#Ed25519
[UCAN Conclusion]:./w3-ucan.md#conclusion
66 changes: 66 additions & 0 deletions w3-ucan.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,70 @@

Enclosing [UCAN] revocation offers a mechanism to revoke authorization that [authority] MAY have given to another principal to revoke [UCAN]s on their behalf.

## Conclusion

### Motivation

The [UCAN invocation] specification defines [receipt] record, that is cryptographically signed description of the invocation output and requested effects. Receipt structure is very similar to [UCAN] except it has no notion of expiry nor it is possible to delegate ability to issue receipt to another principal. To address those shortcomings we define special `ucan/conclude`capability that represents receipt using a special [UCAN] capability.

Check failure on line 210 in w3-ucan.md

View workflow job for this annotation

GitHub Actions / spellcheck

Misspelled word

Misspelled word "cryptographically". Suggested alternatives: "cryptographic ally", "cryptographic-ally", "photographically", "cryptographic", "typographically", "topographically" If you want to ignore this message, add cryptographically to the ignore file at ./.github/workflows/words-to-ignore.txt

### IPLD Schema

```ipldsch
type UCAN union {
| Conclude "ucan/conclude"
} representation inline {
discriminantKey "can"
}

type Conclude struct {
with Authority
nb Conclusion
}

type Conclusion struct {
ran &Invocation
out Result
next [&Task]
Gozala marked this conversation as resolved.
Show resolved Hide resolved
meta Meta
time Int -- Unix timestamp at which the Receipt was issued
}

type Result union {
Any "ok"
{String: Any} "error"
} represantation keyed

type Meta = { String: Any }
```

### Conclusion Authority

The value of the `with` field MUST be the [DID] of the audience of the ran invocation.

### Conclusion Task

The value of the `nb.ran` field MUST be a [link] to the [UCAN invocation] that this receipt is for.

### Conclusion Output

The value output of the invocation in `Result` format.

### Conclusion Effects

Tasks that the invocation would like to enqueue.

### Conclusion Meta

Additional data about the receipt

### Conclusion Time

The UTC Unix timestamp at which the Receipt was issued

### Conclusion Lifetime

Conclusion MAY be permanent or temporary. Enclosing [UCAN] [time-bounds] MUST be interpreted as the time frame within which an issued conclusion is valid.

[UCAN]:https://github.com/ucan-wg/spec/blob/692e8aab59b763a783fe1484131c3f40d997b69a/README.md
[DID]:https://www.w3.org/TR/did-core/
[link]:https://ipld.io/docs/schemas/features/links/
Expand All @@ -212,3 +276,5 @@
[authority]:#authority
[Protocol Labs]:https://protocol.ai/
[Irakli Gozalishvili]:https://github.com/Gozala
[receipt]:https://github.com/ucan-wg/invocation/tree/v0.2?tab=readme-ov-file#225-receipt
[UCAN invocation]:https://github.com/ucan-wg/invocation/tree/v0.2
Loading