From e8c3955c7f6ae54b505d27d8f48f95e4ebe650c2 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 2 Mar 2023 22:21:45 -0500 Subject: [PATCH 01/32] Start on changes to enable workflows --- README.md | 96 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 9ff0e670..bac34615 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# UCAN Invocation Specification v0.1.1 +# UCAN Invocation Specification v0.2.0 ## Editors @@ -195,11 +195,10 @@ An [Effect] are the instruction to the [Executor] to run set of [Task]s concurre ```ipldsch type Task struct { - on URI - call Ability - input {String : Any} - - nnc string + obj URI + call Ability + args {String : Any} + nnc string } type URI string @@ -208,24 +207,52 @@ type Ability string type Authorization struct { # Authorization is denoted by the set of links been authorized scope [&Any] + # Scope signed by the invoker s VarSig } -type Invocation struct { +type Context struct { v SemVer - run &Task + meta {String : Any} + prf [&UCAN] # Receipt of the invocation that caused this invocation cause optional &Invocation +} + +type Invocation struct { + ctx &Context # Task authorization. auth &Authorization +} - meta {String : Any} - - prf [&UCAN] +{ + "ctx": &{ + "v": "0.1.0", + "run": &{ + "obj" "mailto://alice@example.com", + "call": "msg/send", + "input": { + "to": { + "await/ok": {"/": "bafy...getMailingList"} + }, + "subject": "hello", + "body": "world" + } + }, + "meta": { + "gas": 1000, + "timeout": 5000 + }, + "prf": [...] + }, + "auth": &{ + "scope": [...], + "s": "0xabcdef" + } } type SemVer string @@ -286,7 +313,7 @@ Using the JavaScript analogy from the introduction, a Task is similar to wrappin ```json { - "on": "mailto:alice@example.com", + "obj" "mailto:alice@example.com", "call": "msg/send", "input": { "to": [ @@ -314,11 +341,11 @@ Later, when we explore promise [pipelines], this also includes capturing the pro ```json { "bafy...getMailingList": { - "on": "https://exmaple.com/mailinglist", + "obj" "https://exmaple.com/mailinglist", "call": "crud/read" }, "bafy...sendEmail": { - "on": "mailto://alice@example.com", + "obj" "mailto://alice@example.com", "call": "msg/send", "input": { "to": { @@ -347,7 +374,7 @@ const sendEmail = msg.send("mailto://alice@example.com", { ```ipldsch type Task struct { - on URI + obj URI call Ability input {String : Any} nnc string @@ -389,9 +416,9 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { - "on": "https://example.com/blog/posts", + "obj" "https://example.com/blog/posts", "call": "crud/create", - "input": { + "args": { "headers": { "content-type": "application/json" }, @@ -412,7 +439,7 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { - "on": "mailto:akiko@example.com", + "obj" "mailto:akiko@example.com", "call": "msg/send", "input": { "to": [ @@ -429,7 +456,7 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { - "on": "data:application/wasm;base64,AHdhc21lci11bml2ZXJzYWwAAAAAAOAEAAAAAAAAAAD9e7+p/QMAkSAEABH9e8GowANf1uz///8UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAACAAAACoAAAAIAAAABAAAACsAAAAMAAAACAAAANz///8AAAAA1P///wMAAAAlAAAALAAAAAAAAAAUAAAA/Xu/qf0DAJHzDx/44wMBqvMDAqphAkC5YAA/1mACALnzB0H4/XvBqMADX9bU////LAAAAAAAAAAAAAAAAAAAAAAAAAAvVXNlcnMvZXhwZWRlL0Rlc2t0b3AvdGVzdC53YXQAAGFkZF9vbmUHAAAAAAAAAAAAAAAAYWRkX29uZV9mAAAADAAAAAAAAAABAAAAAAAAAAkAAADk////AAAAAPz///8BAAAA9f///wEAAAAAAAAAAQAAAB4AAACM////pP///wAAAACc////AQAAAAAAAAAAAAAAnP///wAAAAAAAAAAlP7//wAAAACM/v//iP///wAAAAABAAAAiP///6D///8BAAAAqP///wEAAACk////AAAAAJz///8AAAAAlP///wAAAACM////AAAAAIT///8AAAAAAAAAAAAAAAAAAAAAAAAAAET+//8BAAAAWP7//wEAAABY/v//AQAAAID+//8BAAAAxP7//wEAAADU/v//AAAAAMz+//8AAAAAxP7//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU////pP///wAAAAAAAQEBAQAAAAAAAACQ////AAAAAIj///8AAAAAAAAAAAAAAADQAQAAAAAAAA==", + "obj" "data:application/wasm;base64,AHdhc21lci11bml2ZXJzYWwAAAAAAOAEAAAAAAAAAAD9e7+p/QMAkSAEABH9e8GowANf1uz///8UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAACAAAACoAAAAIAAAABAAAACsAAAAMAAAACAAAANz///8AAAAA1P///wMAAAAlAAAALAAAAAAAAAAUAAAA/Xu/qf0DAJHzDx/44wMBqvMDAqphAkC5YAA/1mACALnzB0H4/XvBqMADX9bU////LAAAAAAAAAAAAAAAAAAAAAAAAAAvVXNlcnMvZXhwZWRlL0Rlc2t0b3AvdGVzdC53YXQAAGFkZF9vbmUHAAAAAAAAAAAAAAAAYWRkX29uZV9mAAAADAAAAAAAAAABAAAAAAAAAAkAAADk////AAAAAPz///8BAAAA9f///wEAAAAAAAAAAQAAAB4AAACM////pP///wAAAACc////AQAAAAAAAAAAAAAAnP///wAAAAAAAAAAlP7//wAAAACM/v//iP///wAAAAABAAAAiP///6D///8BAAAAqP///wEAAACk////AAAAAJz///8AAAAAlP///wAAAACM////AAAAAIT///8AAAAAAAAAAAAAAAAAAAAAAAAAAET+//8BAAAAWP7//wEAAABY/v//AQAAAID+//8BAAAAxP7//wEAAADU/v//AAAAAMz+//8AAAAAxP7//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU////pP///wAAAAAAAQEBAQAAAAAAAACQ////AAAAAIj///8AAAAAAAAAAAAAAADQAQAAAAAAAA==", "call": "wasm/run", "input": { "func": "add_one", @@ -503,6 +530,7 @@ type Invocation struct { v SemVer run &Task + # Receipt of the invocation that caused this invocation cause optional &Invocation @@ -552,7 +580,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt ```json { "bafy...createBlogPost": { - "on": "https://example.com/blog/posts", + "obj" "https://example.com/blog/posts", "call": "crud/create", "input": { "headers": { @@ -603,7 +631,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt ```json { "bafy...createBlogPostTask": { - "on": "https://example.com/blog/posts", + "obj" "https://example.com/blog/posts", "call": "crud/create", "input": { "headers": { @@ -621,7 +649,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt } }, "bafy...sendEmailTask": { - "on": "mailto:akiko@example.com", + "obj" "mailto:akiko@example.com", "call": "msg/send", "input": { "to": [ @@ -683,7 +711,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt ```json { "bafy...updateDnsTask": { - "on": "dns:example.com?TYPE=TXT", + "obj" "dns:example.com?TYPE=TXT", "call": "crud/update", "input": { "value": "hello world" @@ -1031,7 +1059,7 @@ For example, consider the following invocation batch: ```json { "bafy...createBlogPostTask": { - "on": "https://example.com/blog/posts", + "obj" "https://example.com/blog/posts", "call": "crud/create", "input": { "payload": { @@ -1041,11 +1069,11 @@ For example, consider the following invocation batch: } }, "bafy...getBlogEditorsTask": { - "on": "https://example.com/users/editors", + "obj" "https://example.com/users/editors", "call": "crud/read" }, "bafy...sendEmailTask": { - "on": "mailto:akiko@example.com", + "obj" "mailto:akiko@example.com", "call": "msg/send", "input": { "to": { @@ -1184,14 +1212,14 @@ flowchart BR ```json { "bafy...updateDnsTask": { - "on": "dns:example.com?TYPE=TXT", + "obj" "dns:example.com?TYPE=TXT", "call": "crud/update", "input": { "value": "hello world" } }, "bafy...sendBobEmailTask": { - "on": "mailto://alice@example.com", + "obj" "mailto://alice@example.com", "call": "msg/send", "input": { "to": "bob@example.com", @@ -1204,7 +1232,7 @@ flowchart BR } }, "bafy...sendCarolEmailTask": { - "on": "mailto://alice@example.com", + "obj" "mailto://alice@example.com", "call": "msg/send", "input": { "to": "carol@example.com", @@ -1217,7 +1245,7 @@ flowchart BR } }, "bafy...updateReportTask": { - "on": "https://example.com/report", + "obj" "https://example.com/report", "call": "crud/update", "input": { "payload": { @@ -1357,14 +1385,14 @@ flowchart TB ```json { "bafy...updateDnsTask": { - "on": "dns:example.com?TYPE=TXT", + "obj" "dns:example.com?TYPE=TXT", "call": "crud/update", "input": { "value": "hello world" } }, "bafy...sendBobEmailTask": { - "on": "mailto://alice@example.com", + "obj" "mailto://alice@example.com", "call": "msg/send", "input": { "to": "bob@example.com", @@ -1425,7 +1453,7 @@ flowchart TB ```json { "bafy...emailCarolTask": { - "on": "mailto://alice@example.com", + "obj" "mailto://alice@example.com", "call": "msg/send", "input": { "to": "carol@example.com", @@ -1438,7 +1466,7 @@ flowchart TB } }, "bafy...updateReportTask": { - "on": "https://example.com/report", + "obj" "https://example.com/report", "call": "crud/update", "input": { "payload": { From d4764264ba28a7e28f6d0701f8990b898b0ef505 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 2 Mar 2023 22:24:18 -0500 Subject: [PATCH 02/32] Put schema back --- README.md | 36 ++---------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index bac34615..a3f1da75 100644 --- a/README.md +++ b/README.md @@ -212,49 +212,17 @@ type Authorization struct { s VarSig } -type Context struct { +type Invocation struct { v SemVer run &Task meta {String : Any} prf [&UCAN] + auth &Authorization # Receipt of the invocation that caused this invocation cause optional &Invocation } -type Invocation struct { - ctx &Context - - # Task authorization. - auth &Authorization -} - -{ - "ctx": &{ - "v": "0.1.0", - "run": &{ - "obj" "mailto://alice@example.com", - "call": "msg/send", - "input": { - "to": { - "await/ok": {"/": "bafy...getMailingList"} - }, - "subject": "hello", - "body": "world" - } - }, - "meta": { - "gas": 1000, - "timeout": 5000 - }, - "prf": [...] - }, - "auth": &{ - "scope": [...], - "s": "0xabcdef" - } -} - type SemVer string type Receipt struct { From c066d07f935d2b8a9c4f00174224eed7dba0ad6b Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 2 Mar 2023 22:37:11 -0500 Subject: [PATCH 03/32] Input -> Args --- README.md | 60 +++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index a3f1da75..26ee2c8f 100644 --- a/README.md +++ b/README.md @@ -275,7 +275,7 @@ type Await union { # 3 Task -A Task is the smallest unit of work that can be requested from a UCAN. It describes one `(resource, ability, input)` triple. The `input` field is free form, and depend on the specific resource and ability being interacted with, and is not described in this specification. +A Task is the smallest unit of work that can be requested from a UCAN. It describes one `(resource, ability, arguments)` triple. The `args` field is free form, and depend on the specific resource and ability being interacted with, and is not described in this specification. Using the JavaScript analogy from the introduction, a Task is similar to wrapping a call in an anonymous function: @@ -283,7 +283,7 @@ Using the JavaScript analogy from the introduction, a Task is similar to wrappin { "obj" "mailto:alice@example.com", "call": "msg/send", - "input": { + "args": { "to": [ "bob@example.com", "carol@example.com" @@ -315,7 +315,7 @@ Later, when we explore promise [pipelines], this also includes capturing the pro "bafy...sendEmail": { "obj" "mailto://alice@example.com", "call": "msg/send", - "input": { + "args": { "to": { "await/ok": { "/": "bafy...getMailingList" @@ -342,10 +342,10 @@ const sendEmail = msg.send("mailto://alice@example.com", { ```ipldsch type Task struct { - obj URI - call Ability - input {String : Any} - nnc string + obj URI + call Ability + args {String : Any} + nnc string } ``` @@ -359,20 +359,20 @@ The `on` field MUST contain the [URI](https://en.wikipedia.org/wiki/Uniform_Reso The `call` field MUST contain a [UCAN Ability](https://github.com/ucan-wg/spec/#23-ability). This field can be thought of as the message or trait being sent to the resource. -### 3.2.4 Input +### 3.2.4 Arguments -The OPTIONAL `input` field, MAY contain any parameters expected by the URI/Ability pair, which MAY be different between different URIs and Abilities, and is thus left to the executor to define the shape of this data. +The OPTIONAL `args` field, MAY contain any parameters expected by the URI/Ability pair, which MAY be different between different URIs and Abilities, and is thus left to the executor to define the shape of this data. -If present, `input` field MUST have an IPLD [map representation][ipld representation], and thus MAY be a: +If present, `args` MUST have an IPLD [map representation][ipld representation], and thus MUST be one of the following: 1. [struct](https://ipld.io/docs/schemas/features/representation-strategies/#struct-map-representation) in map representation. 2. [keyed](https://ipld.io/docs/schemas/features/representation-strategies/#union-keyed-representation), [enveloped](https://ipld.io/docs/schemas/features/representation-strategies/#union-envelope-representation) or [inline](https://ipld.io/docs/schemas/features/representation-strategies/#union-inline-representation) union. 3. [unit](https://github.com/ipld/ipld/blob/353baf885adebb93191cbe1f7be34f0517e20bbd/specs/schemas/schema-schema.ipldsch#L753-L789) in empty map representation. 4. [map](https://ipld.io/docs/schemas/features/representation-strategies/#map-map-representation) in map representation. -UCAN capabilities provided in [Proofs] MAY impose certain constraint on the type of `input` allowed. +UCAN capabilities provided in [Proofs] MAY impose certain constraint on the type of `args` allowed. -If `input` field is not present, it is implicitly a `unit` represented as empty map. +If the `args` field is not present, it is implicitly a `unit` represented as empty map. ### 3.2.6 Nonce @@ -409,7 +409,7 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS { "obj" "mailto:akiko@example.com", "call": "msg/send", - "input": { + "args": { "to": [ "boris@example.com", "carol@example.com" @@ -426,7 +426,7 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS { "obj" "data:application/wasm;base64,AHdhc21lci11bml2ZXJzYWwAAAAAAOAEAAAAAAAAAAD9e7+p/QMAkSAEABH9e8GowANf1uz///8UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAACAAAACoAAAAIAAAABAAAACsAAAAMAAAACAAAANz///8AAAAA1P///wMAAAAlAAAALAAAAAAAAAAUAAAA/Xu/qf0DAJHzDx/44wMBqvMDAqphAkC5YAA/1mACALnzB0H4/XvBqMADX9bU////LAAAAAAAAAAAAAAAAAAAAAAAAAAvVXNlcnMvZXhwZWRlL0Rlc2t0b3AvdGVzdC53YXQAAGFkZF9vbmUHAAAAAAAAAAAAAAAAYWRkX29uZV9mAAAADAAAAAAAAAABAAAAAAAAAAkAAADk////AAAAAPz///8BAAAA9f///wEAAAAAAAAAAQAAAB4AAACM////pP///wAAAACc////AQAAAAAAAAAAAAAAnP///wAAAAAAAAAAlP7//wAAAACM/v//iP///wAAAAABAAAAiP///6D///8BAAAAqP///wEAAACk////AAAAAJz///8AAAAAlP///wAAAACM////AAAAAIT///8AAAAAAAAAAAAAAAAAAAAAAAAAAET+//8BAAAAWP7//wEAAABY/v//AQAAAID+//8BAAAAxP7//wEAAADU/v//AAAAAMz+//8AAAAAxP7//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU////pP///wAAAAAAAQEBAQAAAAAAAACQ////AAAAAIj///8AAAAAAAAAAAAAAADQAQAAAAAAAA==", "call": "wasm/run", - "input": { + "args": { "func": "add_one", "args": [ 42 @@ -550,7 +550,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt "bafy...createBlogPost": { "obj" "https://example.com/blog/posts", "call": "crud/create", - "input": { + "args": { "headers": { "content-type": "application/json" }, @@ -601,7 +601,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt "bafy...createBlogPostTask": { "obj" "https://example.com/blog/posts", "call": "crud/create", - "input": { + "args": { "headers": { "content-type": "application/json" }, @@ -619,7 +619,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt "bafy...sendEmailTask": { "obj" "mailto:akiko@example.com", "call": "msg/send", - "input": { + "args": { "to": [ "boris@example.com", "carol@example.com" @@ -681,7 +681,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt "bafy...updateDnsTask": { "obj" "dns:example.com?TYPE=TXT", "call": "crud/update", - "input": { + "args": { "value": "hello world" } }, @@ -1018,7 +1018,7 @@ The `s` field MUST contain a [Varsig] of the [DAG-CBOR] encoded Receipt without There MAY not be enough information to described an Invocation at creation time. However, all of the information required to construct the next request in a sequence MAY be available in the same Batch, or in a previous (but not yet complete) Invocation. -Some invocations MAY require input from set of other invocations. Waiting for each request to complete before proceeding to the next task has a performance impact due to the amount of latency. [Promise pipelining](http://erights.org/elib/distrib/pipeline.html) is a solution to this problem: by referencing a prior invocation, a pipelined invocation can direct the executor to use the output of one invocations into the input of the other. This liberates the invoker from waiting for each step. +Invocations MAY require arguments from the output of other invocations. Waiting for each request to complete before proceeding to the next task has a performance impact due to the amount of latency. [Promise pipelining](http://erights.org/elib/distrib/pipeline.html) is a solution to this problem: by referencing a prior invocation, a pipelined invocation can direct the executor to use the output of one invocations into the input of the other. This liberates the invoker from waiting for each step. An `Await` MAY be used as a variable placeholder for a concrete value in a [Task] [Invocation] output, waiting on a previous step to complete. @@ -1029,7 +1029,7 @@ For example, consider the following invocation batch: "bafy...createBlogPostTask": { "obj" "https://example.com/blog/posts", "call": "crud/create", - "input": { + "args": { "payload": { "title": "How UCAN Tasks Changed My Life", "body": "This is the story of how one spec changed everything..." @@ -1043,7 +1043,7 @@ For example, consider the following invocation batch: "bafy...sendEmailTask": { "obj" "mailto:akiko@example.com", "call": "msg/send", - "input": { + "args": { "to": { "await/ok": { "/": "bafy...getBlogPostEditorsTask" @@ -1155,7 +1155,7 @@ The [Result] output of the [Task] MAY be reference by wrapping the [Task] in the ## 9.3 Dataflow -Pipelining uses [Await] as inputs to determine the required dataflow graph. The following examples both express the following dataflow graph: +Pipelining uses [Await] as arguments to determine the required dataflow graph. The following examples both express the following dataflow graph: ### 9.3.1 Batched @@ -1182,14 +1182,14 @@ flowchart BR "bafy...updateDnsTask": { "obj" "dns:example.com?TYPE=TXT", "call": "crud/update", - "input": { + "args": { "value": "hello world" } }, "bafy...sendBobEmailTask": { "obj" "mailto://alice@example.com", "call": "msg/send", - "input": { + "args": { "to": "bob@example.com", "subject": "DNSLink for example.com", "body": { @@ -1202,7 +1202,7 @@ flowchart BR "bafy...sendCarolEmailTask": { "obj" "mailto://alice@example.com", "call": "msg/send", - "input": { + "args": { "to": "carol@example.com", "subject": "Hey Carol, DNSLink was updated!", "body": { @@ -1215,7 +1215,7 @@ flowchart BR "bafy...updateReportTask": { "obj" "https://example.com/report", "call": "crud/update", - "input": { + "args": { "payload": { "from": "mailto://alice@exmaple.com", "to": [ @@ -1355,14 +1355,14 @@ flowchart TB "bafy...updateDnsTask": { "obj" "dns:example.com?TYPE=TXT", "call": "crud/update", - "input": { + "args": { "value": "hello world" } }, "bafy...sendBobEmailTask": { "obj" "mailto://alice@example.com", "call": "msg/send", - "input": { + "args": { "to": "bob@example.com", "subject": "DNSLink for example.com", "body": { @@ -1423,7 +1423,7 @@ flowchart TB "bafy...emailCarolTask": { "obj" "mailto://alice@example.com", "call": "msg/send", - "input": { + "args": { "to": "carol@example.com", "subject": "Hey Carol, DNSLink was updated!", "body": { @@ -1436,7 +1436,7 @@ flowchart TB "bafy...updateReportTask": { "obj" "https://example.com/report", "call": "crud/update", - "input": { + "args": { "payload": { "from": "mailto://alice@exmaple.com", "to": [ From dacd00fd86331668ec40d15f32e4a5485993b140 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Fri, 3 Mar 2023 17:44:24 -0500 Subject: [PATCH 04/32] Fix typo --- README.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 26ee2c8f..bdc647b8 100644 --- a/README.md +++ b/README.md @@ -281,7 +281,7 @@ Using the JavaScript analogy from the introduction, a Task is similar to wrappin ```json { - "obj" "mailto:alice@example.com", + "obj": "mailto:alice@example.com", "call": "msg/send", "args": { "to": [ @@ -309,11 +309,11 @@ Later, when we explore promise [pipelines], this also includes capturing the pro ```json { "bafy...getMailingList": { - "obj" "https://exmaple.com/mailinglist", + "obj": "https://exmaple.com/mailinglist", "call": "crud/read" }, "bafy...sendEmail": { - "obj" "mailto://alice@example.com", + "obj": "mailto://alice@example.com", "call": "msg/send", "args": { "to": { @@ -384,7 +384,7 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { - "obj" "https://example.com/blog/posts", + "obj": "https://example.com/blog/posts", "call": "crud/create", "args": { "headers": { @@ -407,7 +407,7 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { - "obj" "mailto:akiko@example.com", + "obj": "mailto:akiko@example.com", "call": "msg/send", "args": { "to": [ @@ -424,7 +424,7 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { - "obj" "data:application/wasm;base64,AHdhc21lci11bml2ZXJzYWwAAAAAAOAEAAAAAAAAAAD9e7+p/QMAkSAEABH9e8GowANf1uz///8UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAACAAAACoAAAAIAAAABAAAACsAAAAMAAAACAAAANz///8AAAAA1P///wMAAAAlAAAALAAAAAAAAAAUAAAA/Xu/qf0DAJHzDx/44wMBqvMDAqphAkC5YAA/1mACALnzB0H4/XvBqMADX9bU////LAAAAAAAAAAAAAAAAAAAAAAAAAAvVXNlcnMvZXhwZWRlL0Rlc2t0b3AvdGVzdC53YXQAAGFkZF9vbmUHAAAAAAAAAAAAAAAAYWRkX29uZV9mAAAADAAAAAAAAAABAAAAAAAAAAkAAADk////AAAAAPz///8BAAAA9f///wEAAAAAAAAAAQAAAB4AAACM////pP///wAAAACc////AQAAAAAAAAAAAAAAnP///wAAAAAAAAAAlP7//wAAAACM/v//iP///wAAAAABAAAAiP///6D///8BAAAAqP///wEAAACk////AAAAAJz///8AAAAAlP///wAAAACM////AAAAAIT///8AAAAAAAAAAAAAAAAAAAAAAAAAAET+//8BAAAAWP7//wEAAABY/v//AQAAAID+//8BAAAAxP7//wEAAADU/v//AAAAAMz+//8AAAAAxP7//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU////pP///wAAAAAAAQEBAQAAAAAAAACQ////AAAAAIj///8AAAAAAAAAAAAAAADQAQAAAAAAAA==", + "obj": "data:application/wasm;base64,AHdhc21lci11bml2ZXJzYWwAAAAAAOAEAAAAAAAAAAD9e7+p/QMAkSAEABH9e8GowANf1uz///8UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAACAAAACoAAAAIAAAABAAAACsAAAAMAAAACAAAANz///8AAAAA1P///wMAAAAlAAAALAAAAAAAAAAUAAAA/Xu/qf0DAJHzDx/44wMBqvMDAqphAkC5YAA/1mACALnzB0H4/XvBqMADX9bU////LAAAAAAAAAAAAAAAAAAAAAAAAAAvVXNlcnMvZXhwZWRlL0Rlc2t0b3AvdGVzdC53YXQAAGFkZF9vbmUHAAAAAAAAAAAAAAAAYWRkX29uZV9mAAAADAAAAAAAAAABAAAAAAAAAAkAAADk////AAAAAPz///8BAAAA9f///wEAAAAAAAAAAQAAAB4AAACM////pP///wAAAACc////AQAAAAAAAAAAAAAAnP///wAAAAAAAAAAlP7//wAAAACM/v//iP///wAAAAABAAAAiP///6D///8BAAAAqP///wEAAACk////AAAAAJz///8AAAAAlP///wAAAACM////AAAAAIT///8AAAAAAAAAAAAAAAAAAAAAAAAAAET+//8BAAAAWP7//wEAAABY/v//AQAAAID+//8BAAAAxP7//wEAAADU/v//AAAAAMz+//8AAAAAxP7//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU////pP///wAAAAAAAQEBAQAAAAAAAACQ////AAAAAIj///8AAAAAAAAAAAAAAADQAQAAAAAAAA==", "call": "wasm/run", "args": { "func": "add_one", @@ -548,7 +548,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt ```json { "bafy...createBlogPost": { - "obj" "https://example.com/blog/posts", + "obj": "https://example.com/blog/posts", "call": "crud/create", "args": { "headers": { @@ -599,7 +599,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt ```json { "bafy...createBlogPostTask": { - "obj" "https://example.com/blog/posts", + "obj": "https://example.com/blog/posts", "call": "crud/create", "args": { "headers": { @@ -617,7 +617,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt } }, "bafy...sendEmailTask": { - "obj" "mailto:akiko@example.com", + "obj": "mailto:akiko@example.com", "call": "msg/send", "args": { "to": [ @@ -679,7 +679,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt ```json { "bafy...updateDnsTask": { - "obj" "dns:example.com?TYPE=TXT", + "obj": "dns:example.com?TYPE=TXT", "call": "crud/update", "args": { "value": "hello world" @@ -1027,7 +1027,7 @@ For example, consider the following invocation batch: ```json { "bafy...createBlogPostTask": { - "obj" "https://example.com/blog/posts", + "obj": "https://example.com/blog/posts", "call": "crud/create", "args": { "payload": { @@ -1037,11 +1037,11 @@ For example, consider the following invocation batch: } }, "bafy...getBlogEditorsTask": { - "obj" "https://example.com/users/editors", + "obj": "https://example.com/users/editors", "call": "crud/read" }, "bafy...sendEmailTask": { - "obj" "mailto:akiko@example.com", + "obj": "mailto:akiko@example.com", "call": "msg/send", "args": { "to": { @@ -1180,14 +1180,14 @@ flowchart BR ```json { "bafy...updateDnsTask": { - "obj" "dns:example.com?TYPE=TXT", + "obj": "dns:example.com?TYPE=TXT", "call": "crud/update", "args": { "value": "hello world" } }, "bafy...sendBobEmailTask": { - "obj" "mailto://alice@example.com", + "obj": "mailto://alice@example.com", "call": "msg/send", "args": { "to": "bob@example.com", @@ -1200,7 +1200,7 @@ flowchart BR } }, "bafy...sendCarolEmailTask": { - "obj" "mailto://alice@example.com", + "obj": "mailto://alice@example.com", "call": "msg/send", "args": { "to": "carol@example.com", @@ -1213,7 +1213,7 @@ flowchart BR } }, "bafy...updateReportTask": { - "obj" "https://example.com/report", + "obj": "https://example.com/report", "call": "crud/update", "args": { "payload": { @@ -1353,14 +1353,14 @@ flowchart TB ```json { "bafy...updateDnsTask": { - "obj" "dns:example.com?TYPE=TXT", + "obj": "dns:example.com?TYPE=TXT", "call": "crud/update", "args": { "value": "hello world" } }, "bafy...sendBobEmailTask": { - "obj" "mailto://alice@example.com", + "obj": "mailto://alice@example.com", "call": "msg/send", "args": { "to": "bob@example.com", @@ -1421,7 +1421,7 @@ flowchart TB ```json { "bafy...emailCarolTask": { - "obj" "mailto://alice@example.com", + "obj": "mailto://alice@example.com", "call": "msg/send", "args": { "to": "carol@example.com", @@ -1434,7 +1434,7 @@ flowchart TB } }, "bafy...updateReportTask": { - "obj" "https://example.com/report", + "obj": "https://example.com/report", "call": "crud/update", "args": { "payload": { From 18c7d9a82ea040a7db156c8459a0daca24f22af2 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 23 Mar 2023 12:16:42 -0700 Subject: [PATCH 05/32] Rename fields --- README.md | 100 +++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index bdc647b8..f9141e4b 100644 --- a/README.md +++ b/README.md @@ -195,10 +195,10 @@ An [Effect] are the instruction to the [Executor] to run set of [Task]s concurre ```ipldsch type Task struct { - obj URI + uri URI call Ability - args {String : Any} - nnc string + input {String : Any} + nnc string (implicit "") } type URI string @@ -281,9 +281,9 @@ Using the JavaScript analogy from the introduction, a Task is similar to wrappin ```json { - "obj": "mailto:alice@example.com", + "uri" "mailto:alice@example.com", "call": "msg/send", - "args": { + "input": { "to": [ "bob@example.com", "carol@example.com" @@ -309,13 +309,13 @@ Later, when we explore promise [pipelines], this also includes capturing the pro ```json { "bafy...getMailingList": { - "obj": "https://exmaple.com/mailinglist", + "uri" "https://exmaple.com/mailinglist", "call": "crud/read" }, "bafy...sendEmail": { - "obj": "mailto://alice@example.com", + "uri" "mailto://alice@example.com", "call": "msg/send", - "args": { + "input": { "to": { "await/ok": { "/": "bafy...getMailingList" @@ -342,10 +342,10 @@ const sendEmail = msg.send("mailto://alice@example.com", { ```ipldsch type Task struct { - obj URI - call Ability - args {String : Any} - nnc string + uri URI + call Ability + input {String : Any} + nnc string (implicit "") } ``` @@ -370,9 +370,9 @@ If present, `args` MUST have an IPLD [map representation][ipld representation], 3. [unit](https://github.com/ipld/ipld/blob/353baf885adebb93191cbe1f7be34f0517e20bbd/specs/schemas/schema-schema.ipldsch#L753-L789) in empty map representation. 4. [map](https://ipld.io/docs/schemas/features/representation-strategies/#map-map-representation) in map representation. -UCAN capabilities provided in [Proofs] MAY impose certain constraint on the type of `args` allowed. +UCAN capabilities provided in [Proofs] MAY impose certain constraint on the type of `input`s allowed. -If the `args` field is not present, it is implicitly a `unit` represented as empty map. +If the `input` field is not present, it is implicitly a `unit` represented as empty map. ### 3.2.6 Nonce @@ -384,9 +384,9 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { - "obj": "https://example.com/blog/posts", + "uri" "https://example.com/blog/posts", "call": "crud/create", - "args": { + "input": { "headers": { "content-type": "application/json" }, @@ -407,9 +407,9 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { - "obj": "mailto:akiko@example.com", + "uri" "mailto:akiko@example.com", "call": "msg/send", - "args": { + "input": { "to": [ "boris@example.com", "carol@example.com" @@ -424,11 +424,11 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { - "obj": "data:application/wasm;base64,AHdhc21lci11bml2ZXJzYWwAAAAAAOAEAAAAAAAAAAD9e7+p/QMAkSAEABH9e8GowANf1uz///8UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAACAAAACoAAAAIAAAABAAAACsAAAAMAAAACAAAANz///8AAAAA1P///wMAAAAlAAAALAAAAAAAAAAUAAAA/Xu/qf0DAJHzDx/44wMBqvMDAqphAkC5YAA/1mACALnzB0H4/XvBqMADX9bU////LAAAAAAAAAAAAAAAAAAAAAAAAAAvVXNlcnMvZXhwZWRlL0Rlc2t0b3AvdGVzdC53YXQAAGFkZF9vbmUHAAAAAAAAAAAAAAAAYWRkX29uZV9mAAAADAAAAAAAAAABAAAAAAAAAAkAAADk////AAAAAPz///8BAAAA9f///wEAAAAAAAAAAQAAAB4AAACM////pP///wAAAACc////AQAAAAAAAAAAAAAAnP///wAAAAAAAAAAlP7//wAAAACM/v//iP///wAAAAABAAAAiP///6D///8BAAAAqP///wEAAACk////AAAAAJz///8AAAAAlP///wAAAACM////AAAAAIT///8AAAAAAAAAAAAAAAAAAAAAAAAAAET+//8BAAAAWP7//wEAAABY/v//AQAAAID+//8BAAAAxP7//wEAAADU/v//AAAAAMz+//8AAAAAxP7//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU////pP///wAAAAAAAQEBAQAAAAAAAACQ////AAAAAIj///8AAAAAAAAAAAAAAADQAQAAAAAAAA==", + "uri" "data:application/wasm;base64,AHdhc21lci11bml2ZXJzYWwAAAAAAOAEAAAAAAAAAAD9e7+p/QMAkSAEABH9e8GowANf1uz///8UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAACAAAACoAAAAIAAAABAAAACsAAAAMAAAACAAAANz///8AAAAA1P///wMAAAAlAAAALAAAAAAAAAAUAAAA/Xu/qf0DAJHzDx/44wMBqvMDAqphAkC5YAA/1mACALnzB0H4/XvBqMADX9bU////LAAAAAAAAAAAAAAAAAAAAAAAAAAvVXNlcnMvZXhwZWRlL0Rlc2t0b3AvdGVzdC53YXQAAGFkZF9vbmUHAAAAAAAAAAAAAAAAYWRkX29uZV9mAAAADAAAAAAAAAABAAAAAAAAAAkAAADk////AAAAAPz///8BAAAA9f///wEAAAAAAAAAAQAAAB4AAACM////pP///wAAAACc////AQAAAAAAAAAAAAAAnP///wAAAAAAAAAAlP7//wAAAACM/v//iP///wAAAAABAAAAiP///6D///8BAAAAqP///wEAAACk////AAAAAJz///8AAAAAlP///wAAAACM////AAAAAIT///8AAAAAAAAAAAAAAAAAAAAAAAAAAET+//8BAAAAWP7//wEAAABY/v//AQAAAID+//8BAAAAxP7//wEAAADU/v//AAAAAMz+//8AAAAAxP7//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU////pP///wAAAAAAAQEBAQAAAAAAAACQ////AAAAAIj///8AAAAAAAAAAAAAAADQAQAAAAAAAA==", "call": "wasm/run", - "args": { + "input": { "func": "add_one", - "args": [ + "input": [ 42 ] } @@ -548,9 +548,9 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt ```json { "bafy...createBlogPost": { - "obj": "https://example.com/blog/posts", + "uri" "https://example.com/blog/posts", "call": "crud/create", - "args": { + "input": { "headers": { "content-type": "application/json" }, @@ -599,9 +599,9 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt ```json { "bafy...createBlogPostTask": { - "obj": "https://example.com/blog/posts", + "uri" "https://example.com/blog/posts", "call": "crud/create", - "args": { + "input": { "headers": { "content-type": "application/json" }, @@ -617,9 +617,9 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt } }, "bafy...sendEmailTask": { - "obj": "mailto:akiko@example.com", + "uri" "mailto:akiko@example.com", "call": "msg/send", - "args": { + "input": { "to": [ "boris@example.com", "carol@example.com" @@ -679,9 +679,9 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt ```json { "bafy...updateDnsTask": { - "obj": "dns:example.com?TYPE=TXT", + "uri" "dns:example.com?TYPE=TXT", "call": "crud/update", - "args": { + "input": { "value": "hello world" } }, @@ -1027,9 +1027,9 @@ For example, consider the following invocation batch: ```json { "bafy...createBlogPostTask": { - "obj": "https://example.com/blog/posts", + "uri" "https://example.com/blog/posts", "call": "crud/create", - "args": { + "input": { "payload": { "title": "How UCAN Tasks Changed My Life", "body": "This is the story of how one spec changed everything..." @@ -1037,13 +1037,13 @@ For example, consider the following invocation batch: } }, "bafy...getBlogEditorsTask": { - "obj": "https://example.com/users/editors", + "uri" "https://example.com/users/editors", "call": "crud/read" }, "bafy...sendEmailTask": { - "obj": "mailto:akiko@example.com", + "uri" "mailto:akiko@example.com", "call": "msg/send", - "args": { + "input": { "to": { "await/ok": { "/": "bafy...getBlogPostEditorsTask" @@ -1180,16 +1180,16 @@ flowchart BR ```json { "bafy...updateDnsTask": { - "obj": "dns:example.com?TYPE=TXT", + "uri" "dns:example.com?TYPE=TXT", "call": "crud/update", - "args": { + "input": { "value": "hello world" } }, "bafy...sendBobEmailTask": { - "obj": "mailto://alice@example.com", + "uri" "mailto://alice@example.com", "call": "msg/send", - "args": { + "input": { "to": "bob@example.com", "subject": "DNSLink for example.com", "body": { @@ -1200,9 +1200,9 @@ flowchart BR } }, "bafy...sendCarolEmailTask": { - "obj": "mailto://alice@example.com", + "uri" "mailto://alice@example.com", "call": "msg/send", - "args": { + "input": { "to": "carol@example.com", "subject": "Hey Carol, DNSLink was updated!", "body": { @@ -1213,9 +1213,9 @@ flowchart BR } }, "bafy...updateReportTask": { - "obj": "https://example.com/report", + "uri" "https://example.com/report", "call": "crud/update", - "args": { + "input": { "payload": { "from": "mailto://alice@exmaple.com", "to": [ @@ -1353,16 +1353,16 @@ flowchart TB ```json { "bafy...updateDnsTask": { - "obj": "dns:example.com?TYPE=TXT", + "uri" "dns:example.com?TYPE=TXT", "call": "crud/update", - "args": { + "input": { "value": "hello world" } }, "bafy...sendBobEmailTask": { - "obj": "mailto://alice@example.com", + "uri" "mailto://alice@example.com", "call": "msg/send", - "args": { + "input": { "to": "bob@example.com", "subject": "DNSLink for example.com", "body": { @@ -1421,9 +1421,9 @@ flowchart TB ```json { "bafy...emailCarolTask": { - "obj": "mailto://alice@example.com", + "uri" "mailto://alice@example.com", "call": "msg/send", - "args": { + "input": { "to": "carol@example.com", "subject": "Hey Carol, DNSLink was updated!", "body": { @@ -1434,9 +1434,9 @@ flowchart TB } }, "bafy...updateReportTask": { - "obj": "https://example.com/report", + "uri" "https://example.com/report", "call": "crud/update", - "args": { + "input": { "payload": { "from": "mailto://alice@exmaple.com", "to": [ From 67133628325f4923032ef8eefd4a229b035309dd Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 23 Mar 2023 15:05:04 -0700 Subject: [PATCH 06/32] Remove implicit nnc --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f9141e4b..112699e3 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,7 @@ type Task struct { uri URI call Ability input {String : Any} - nnc string (implicit "") + nnc String } type URI string @@ -345,7 +345,7 @@ type Task struct { uri URI call Ability input {String : Any} - nnc string (implicit "") + nnc String } ``` From f07a92e10cd7ecee589b15b0f064ca9c635be75a Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 23 Mar 2023 22:37:56 -0700 Subject: [PATCH 07/32] Update schmea with capsule types etc --- README.md | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 112699e3..fa579e59 100644 --- a/README.md +++ b/README.md @@ -204,39 +204,31 @@ type Task struct { type URI string type Ability string -type Authorization struct { - # Authorization is denoted by the set of links been authorized - scope [&Any] - - # Scope signed by the invoker - s VarSig -} - -type Invocation struct { - v SemVer +type Context struct { run &Task meta {String : Any} prf [&UCAN] - auth &Authorization # Receipt of the invocation that caused this invocation cause optional &Invocation } -type SemVer string +type Invocation struct { + ctx Context + sig Varsig +} -type Receipt struct { - # Invocation this is a receipt for - ran &Invocation +type InvocationCapsule struct { + inv Invocation (rename "ucan/invoke@0.2.0") +} - # Output of the invocation - out Result +type Trace struct { + ran &Invocation # Invocation this is a receipt for - # Effects to be performed - fx Effects - - # All the other metadata - meta {String : Any} + out Result # Output of the invocation + fx Effects # Effects to be enqueued + + meta {String : Any} # All the other metadata # Principal that issued this receipt. If omitted issuer is # inferred from the invocation task audience. @@ -246,9 +238,15 @@ type Receipt struct { # delegation chain from executor to the issuer. This should be # omitted when the executor is the issuer. prf [&UCAN] +} - # Signature from the "iss". - s Varsig +type Receipt struct { + trc Trace + sig Varsig +} + +type ReceiptCapsule struct { + rct &Receipt (rename "ucan/receipt@0.2.0") } type Result union { From 6bde69c5cadc7f562a52a2dafbaa9aefb8eb2d19 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 23 Mar 2023 22:43:49 -0700 Subject: [PATCH 08/32] Typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fa579e59..850e5bf5 100644 --- a/README.md +++ b/README.md @@ -246,7 +246,7 @@ type Receipt struct { } type ReceiptCapsule struct { - rct &Receipt (rename "ucan/receipt@0.2.0") + rct Receipt (rename "ucan/receipt@0.2.0") } type Result union { From 17ac2427dbcc32722853793928decb2507a88438 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 23 Mar 2023 23:00:51 -0700 Subject: [PATCH 09/32] arg -> input in the last few places --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 850e5bf5..514c3cc3 100644 --- a/README.md +++ b/README.md @@ -273,7 +273,7 @@ type Await union { # 3 Task -A Task is the smallest unit of work that can be requested from a UCAN. It describes one `(resource, ability, arguments)` triple. The `args` field is free form, and depend on the specific resource and ability being interacted with, and is not described in this specification. +A Task is the smallest unit of work that can be requested from a UCAN. It describes one `(resource, ability, input)` triple. The `input` field is free form, and depend on the specific resource and ability being interacted with, and is not described in this specification. Using the JavaScript analogy from the introduction, a Task is similar to wrapping a call in an anonymous function: @@ -357,16 +357,16 @@ The `on` field MUST contain the [URI](https://en.wikipedia.org/wiki/Uniform_Reso The `call` field MUST contain a [UCAN Ability](https://github.com/ucan-wg/spec/#23-ability). This field can be thought of as the message or trait being sent to the resource. -### 3.2.4 Arguments +### 3.2.4 Input -The OPTIONAL `args` field, MAY contain any parameters expected by the URI/Ability pair, which MAY be different between different URIs and Abilities, and is thus left to the executor to define the shape of this data. +The `input` field, MAY contain any parameters expected by the URI/Ability pair, which MAY be different between different URIs and Abilities, and is thus left to the executor to define the shape of this data. -If present, `args` MUST have an IPLD [map representation][ipld representation], and thus MUST be one of the following: +The `input` field MUST have an IPLD [map representation][ipld representation], and thus MUST be one of the following: -1. [struct](https://ipld.io/docs/schemas/features/representation-strategies/#struct-map-representation) in map representation. -2. [keyed](https://ipld.io/docs/schemas/features/representation-strategies/#union-keyed-representation), [enveloped](https://ipld.io/docs/schemas/features/representation-strategies/#union-envelope-representation) or [inline](https://ipld.io/docs/schemas/features/representation-strategies/#union-inline-representation) union. -3. [unit](https://github.com/ipld/ipld/blob/353baf885adebb93191cbe1f7be34f0517e20bbd/specs/schemas/schema-schema.ipldsch#L753-L789) in empty map representation. -4. [map](https://ipld.io/docs/schemas/features/representation-strategies/#map-map-representation) in map representation. +1. [Struct](https://ipld.io/docs/schemas/features/representation-strategies/#struct-map-representation) in map representation. +2. [Keyed](https://ipld.io/docs/schemas/features/representation-strategies/#union-keyed-representation), [enveloped](https://ipld.io/docs/schemas/features/representation-strategies/#union-envelope-representation) or [inline](https://ipld.io/docs/schemas/features/representation-strategies/#union-inline-representation) union. +3. [Unit](https://github.com/ipld/ipld/blob/353baf885adebb93191cbe1f7be34f0517e20bbd/specs/schemas/schema-schema.ipldsch#L753-L789) in empty map representation. +4. [Map](https://ipld.io/docs/schemas/features/representation-strategies/#map-map-representation) in map representation. UCAN capabilities provided in [Proofs] MAY impose certain constraint on the type of `input`s allowed. From 6a614e74c0f0eb89d31927d39bfb1f20f02a6a84 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 23 Mar 2023 23:48:56 -0700 Subject: [PATCH 10/32] Updating to capsules --- README.md | 184 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 109 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index 514c3cc3..02cf08d6 100644 --- a/README.md +++ b/README.md @@ -489,59 +489,81 @@ The `auth` field MUST be contain an [Authorization] which signs over the `&Task` Concretely, this means that the `&Task` MUST be present in the associated `auth`'s `scope` field. An `Invocation` where the associated [Authorization] does not include the [Task] in the `scope` MUST be considered invalid. -## 5.1 Schema +## 5.1 Context ```ipldsch -type Invocation struct { - v SemVer - +type Context struct { run &Task + meta {String : Any} + prf [&UCAN] # Receipt of the invocation that caused this invocation cause optional &Invocation +} +``` - # Task authorization. - auth &Authorization +### 5.1.1 Task - meta {String : any} +The `run` field MUST contain a link to the [Task] to be run. - prf [&UCAN] -} +### 5.1.2 Metadata -type SemVer string +The OPTIONAL `meta` field MAY be used to include human-readable descriptions, tags, execution hints, resource limits, and so on. If present, the `meta` field MUST contain a map with string keys. The contents of the map are left undefined to encourage extensible use. + +If `meta` field is not present, it is implicitly a `unit` represented as an empty map. + +### 5.1.3 Proofs + +The `prf` field MUST contain links to any UCANs that provide the authority to perform this task. All of the outermost proofs MUST have `aud` field set to the [Executor]'s DID. All of the outmost proofs MUST have `iss` field set to the [Invoker]'s DID. + +### 5.1.4 Cause + +[Task]s MAY be invoked as an effect caused by a prior [Invocation]. Such [Invocation]s SHOULD have a `cause` field set to the [Receipt] link of the [Invocation] that caused it. The linked [Receipt] MUST have an `Effect` (the `fx` field) containing invoked [Task] in the `run` field. + +## 5.2 (Signed) Invocation + +An `Invocation` is a signed `Context`. + +```ipldsch +type Invocation struct { + ctx Context + sig Varsig +} ``` -## 5.2 Fields +### 5.2.1 Context -### 5.2.1 UCAN Task Version +The `Context` containing the `Task` and any configuration. -The `v` field MUST contain the SemVer-formatted version of the UCAN Invocation Specification that this struct conforms to. +### 5.2.2 Signature -### 5.2.2 Task +The `sig` field MUST contain a [varsig] of the `Context`, signed by the issuer of the proofs. -The `run` field MUST contain a link to the [Task] to be run. +## 5.3 Capsule -### 5.2.3 Cause +An invocation capsule associates the `Invocation` with a versioned schema. This MAY be omitted in contexts where the schema and version are clear from context (for example, when nested in another structure that defines the version) -[Task]s MAY be invoked as an effect caused by a prior [Invocation]. Such [Invocation]s SHOULD have a `cause` field set to the [Receipt] link of the [Invocation] that caused it. The linked [Receipt] MUST have an `Effect` (the `fx` field) containing invoked [Task] in the `run` field. +```ipldsch +type InvocationCapsule struct { + inv Invocation (rename "ucan/invoke@0.2.0") +} +``` -### 5.2.4 Authorization +## 5.4 DAG-JSON Example -The `auth` field MUST contain a link to the [Authorization] that authorizes invoked [Task] in the `run` field. The linked [Authorization] MUST contain `run` in its `scope`. +### 5.4.1 Single Invocation -### 5.2.4 Proofs -The `prf` field MUST contain links to any UCANs that provide the authority to perform this task. All of the outermost proofs MUST have `aud` field set to the [Executor]'s DID. All of the outmost proofs MUST have `iss` field set to the [Invoker]'s DID. -### 5.2.6 Metadata -The OPTIONAL `meta` field MAY be used to include human-readable descriptions, tags, execution hints, resource limits, and so on. If present, the `meta` field MUST contain a map with string keys. The contents of the map are left undefined to encourage extensible use. -If `meta` field is not present, it is implicitly a `unit` represented as an empty map. -## 5.3 DAG-JSON Example +// FIXME + + + + -### 5.3.1 Single Invocation ```json { @@ -592,7 +614,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt } ``` -### 5.3.1 Multiple Invocations +### 5.4.2 Multiple Invocations ```json { @@ -672,7 +694,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt } ``` -### 5.3.3 Causal Invocations +### 5.4.3 Causal Invocations ```json { @@ -842,74 +864,86 @@ A `Receipt` is an attestation of the [Result] and requested [Effect]s by a [Task Receipts MUST use the same version as the invocation that they contain. -## 8.1 Schema +## 8.1 Trace ```ipldsch -type Receipt struct { - ran &Invocation - - # output of the invocation - out Result +type Trace struct { + ran &Invocation # Invocation this is a receipt for - # Effects to be performed - fx Effects + out Result # Output of the invocation + fx Effects # Effects to be enqueued - # All the other metadata - meta {String: any} + meta {String : Any} # All the other metadata - # Principal that issued this receipt. - # If omitted issuer is inferred from - # the invocation task audience. + # Principal that issued this receipt. If omitted issuer is + # inferred from the invocation task audience. iss optional Principal - # When issuer is different from executor - # this MUST hold a UCAN delegation chain - # from executor to the issuer. - # This field SHOULD be omitted executor is an issuer. + # When issuer is different from executor this MUST hold a UCAN + # delegation chain from executor to the issuer. This should be + # omitted when the executor is the issuer. prf [&UCAN] - - # Signature from the `iss`. - s Varsig } ``` -## 8.2 Fields - -### 8.2.1 Ran Invocation +### 8.1.1 Ran Invocation The `ran` field MUST include a link to the [Invocation] that the Receipt is for. -### 8.2.2 Output +### 8.1.2 Output The `out` field MUST contain the value output of the invocation in [Result] format. -### 8.2.3 Effect +### 8.1.3 Effect The OPTIONAL `fx` field, if present MUST be set to the caused [Effect]. The [Executor] SHOULD invoke contained [Task] to progress a workflow execution. If `fx` does not contain OPTIONAL `join` field, it denotes completion of the current execution thread. -### 8.2.4 Metadata Fields +### 8.1.4 Metadata Fields The OPTIONAL metadata field MAY be omitted or used to contain additional data about the receipt. This field MAY be used for tags, commentary, trace information, and so on. -### 8.2.5 Receipt Issuer +### 8.1.5 Receipt Issuer The OPTIONAL `iss` field, if present MUST contain the DID of the [Executor] delegate that signed it. If field is present, delegation from [Executor] MUST be included in the `prf` field. If `iss` field is omitted, Receipt MUST be signed by the [Executor]. -### 8.2.6 Proofs +### 8.1.6 Proofs If OPTIONAL `prf` field is present, MUST contain link to UCAN delegation authorizing Receipt Issuer (`iss`) to carry [Task] execution. -### 8.2.7 Signature +## 8.2 Receipt + +```ipldsch +type Receipt struct { + trc Trace + sig Varsig +} +``` + +### 8.2.1 Trace -The `s` field MUST contain a [Varsig] of the [DAG-CBOR] encoded Receipt without `s` field. The signature MUST be generated by the [Executor] or a delegate if OPTIONAL `iss` field is set. +The `trc` field MUST contain the `Trace` of the `Invocation` that the recept is for. -## 8.3 DAG-JSON Examples +### 8.2.2 Signature -### 8.3.1 Issued by Executor +The `sig` field MUST contain a [Varsig] of the [DAG-CBOR] encoded Receipt without `s` field. The signature MUST be generated by the [Executor] or a delegate if OPTIONAL `iss` field is set. + +## 8.3 Capsule + +```ipldsch +type ReceiptCapsule struct { + rct Receipt (rename "ucan/receipt@0.2.0") +} +``` + +A receipt capsule associates the `Receipt` with a versioned schema. This MAY be omitted in contexts where the schema and version are clear from context (for example, when nested in another structure that defines the version). + +## 8.4 DAG-JSON Examples + +### 8.4.1 Issued by Executor ```json { @@ -939,7 +973,7 @@ The `s` field MUST contain a [Varsig] of the [DAG-CBOR] encoded Receipt without } ``` -### 8.3.2 Issued by Delegate +### 8.4.2 Issued by Delegate ```json { @@ -975,7 +1009,7 @@ The `s` field MUST contain a [Varsig] of the [DAG-CBOR] encoded Receipt without } ``` -### 7.3.3 Receipt with effects +### 8.4.3 Receipt with effects ```json { @@ -1535,20 +1569,20 @@ Thanks to [Christine Lemmer-Webber](https://github.com/cwebber) for the many con Thanks to [Rod Vagg](https://github.com/rvagg/) for the clarifications on IPLD Schema implicits and the general IPLD worldview. -[dag-json]: https://ipld.io/docs/codecs/known/dag-json/ -[varsig]: https://github.com/ChainAgnostic/varsig/ -[ucan-ipld]: https://github.com/ucan-wg/ucan-ipld/ -[ucan]: https://github.com/ucan-wg/spec/ +[authorization]: #4-authorization +[await]: #await [dag-cbor]: https://ipld.io/specs/codecs/dag-cbor/spec/ -[ipld representation]: https://ipld.io/docs/schemas/features/representation-strategies/ -[lazy-vs-eager]: #112-lazy-vs-eager-evaluation -[invoker]: #211-invoker +[dag-json]: https://ipld.io/docs/codecs/known/dag-json/ +[effect]: #7-effect [executor]: #212-executor -[task]: #3-task -[authorization]: #4-authorization [invocation]: #5-invocation -[result]: #6-result -[effect]: #7-effect -[receipt]: #8-receipt +[invoker]: #211-invoker +[ipld representation]: https://ipld.io/docs/schemas/features/representation-strategies/ +[lazy-vs-eager]: #112-lazy-vs-eager-evaluation [pipelines]: #9-pipelines -[await]: #await +[receipt]: #8-receipt +[result]: #6-result +[task]: #3-task +[ucan-ipld]: https://github.com/ucan-wg/ucan-ipld/ +[ucan]: https://github.com/ucan-wg/spec/ +[varsig]: https://github.com/ChainAgnostic/varsig/ From cfe5a4edbcddb3aea8ac44ca799e7495e8c7e672 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Fri, 24 Mar 2023 00:20:41 -0700 Subject: [PATCH 11/32] Updating examples --- README.md | 84 ++++++++++++++----------------------------------------- 1 file changed, 21 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 02cf08d6..82577788 100644 --- a/README.md +++ b/README.md @@ -435,6 +435,8 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS # 4 Authorization +// FIXME? + An [Authorization] is cryptographically signed data set. It represents an authorization to run [Task]s that are included in `scope` data set. ## 4.1 Schema @@ -442,7 +444,7 @@ An [Authorization] is cryptographically signed data set. It represents an author ```ipldsch type Authorization struct { # Authorization is denoted by the set of links been authorized - scope [&Any] (implicit []) + scope [&Any] # Scope signed by the invoker s VarSig @@ -648,48 +650,19 @@ type InvocationCapsule struct { "subject": "Coffee" } }, - "bafy...multipleAuth": { - "scope": [ - { - "/": "bafy...sendEmailTask" - }, - { - "/": "bafy...createBlogPostTask" - } - ], - "s": { - "/": { - "bytes": "7aEDQMyGqYw2iwP7uIn+Kav5AWe9l5VnL72Gpkzs1Azp+zs6vnixQPa1aCSrok4XwKkhSlFRmRN8YbyohB6iDFl4CQ8" - } - } - }, "bafy...createBlogPostInvocation": { - "v": "0.1.0", - "run": { - "/": "bafy...createBlogPostTask" - }, - "auth": { - "/": "bafy...multipleAuth" + "ctx": { + "run": {"/": "bafy...createBlogPostTask"}, + "prf": [{"/": "bafyreid6q7uslc33xqvodeysekliwzs26u5wglas3u4ndlzkelolbt5z3a"}] }, - "prf": [ - { - "/": "bafyreid6q7uslc33xqvodeysekliwzs26u5wglas3u4ndlzkelolbt5z3a" - } - ] + "sig": {"/": "bafy...multipleAuth"} }, "bafy...sendEmailInvocation": { - "v": "0.1.0", - "run": { - "/": "bafy...sendEmailTask" - }, - "auth": { - "/": "bafy...multipleAuth" + "ctx": { + "run": {"/": "bafy...sendEmailTask"}, + "prf": [{"/": "bafyreihvee5irbkfxspsim5s2zk2onb7hictmpbf5lne2nvq6xanmbm6e4"}] }, - "prf": [ - { - "/": "bafyreihvee5irbkfxspsim5s2zk2onb7hictmpbf5lne2nvq6xanmbm6e4" - } - ] + "sig": {"/": "bafy...multipleAuth"}, } } ``` @@ -1089,33 +1062,18 @@ For example, consider the following invocation batch: } } }, - "bafy...sendEmailInvoctaion": { - "v": "0.1.0", - "run": { - "/": "bafy...sendEmailTask" - }, - "auth": { - "/": "bafy...auth" - }, - "prf": [ - { - "/": "bafy...proofUcanOutsideExample" - } - ] - }, - "bafy...auth": { - "scope": [ - { + "bafy...sendEmailInvocation": { + "ctx": { + "run": { "/": "bafy...sendEmailTask" }, - { - "/": "bafy...getBlogPostEditorsTask" - }, - { - "/": "bafy...createBlogPostTask" - } - ], - "s": { + "prf": [ + { + "/": "bafy...proofUcanOutsideExample" + } + ] + }, + "sig": { "/": { "bytes": "7aEDQDEGkezG7Bcpeknf2UJ7hpqeL1PZodrYYTSwRjqZPf67P4r1lRZvX+6+9gV+wDZUX0DZLMv64n2fPKnjvxrEugE" } From 7989910044b0fc116bcdc06db84a1bec59313af8 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Fri, 24 Mar 2023 17:05:16 -0700 Subject: [PATCH 12/32] Update schema --- README.md | 92 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 82577788..c841404c 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Akiko is going away for the weekend. Her good friend Boris is going to borrow he ## 1.1.2 Lazy vs Eager Evaluation -In a referentially transparent setting, the description of a task is equivalent to having done so: a function and its results are interchangeable. [Programming languages with call-by-need semantics](https://en.wikipedia.org/wiki/Haskell) have shown that this can be an elegant programming model, especially for pure functions. However, _when_ something will run can sometimes be unclear. +In a referentially transparent setting, the description of a task is equivalent to having done so: a function and its results are interchangeable. [Programming languages with call-by-need semantics][Haskell] have shown that this can be an elegant programming model, especially for pure functions. However, _when_ something will run can sometimes be unclear. Most languages use eager evaluation. Eager languages must contend directly with the distinction between a reference to a function and a command to run it. For instance, in JavaScript, adding parentheses to a function will run it. Omitting them lets the program pass around a reference to the function without immediately invoking it. @@ -194,9 +194,9 @@ An [Effect] are the instruction to the [Executor] to run set of [Task]s concurre ## 2.3 IPLD Schema ```ipldsch -type Task struct { - uri URI - call Ability +type Instruction struct { + rsc URI + op Ability input {String : Any} nnc String } @@ -204,8 +204,8 @@ type Task struct { type URI string type Ability string -type Context struct { - run &Task +type Task struct { + run &Instruction meta {String : Any} prf [&UCAN] @@ -213,16 +213,21 @@ type Context struct { cause optional &Invocation } -type Invocation struct { - ctx Context - sig Varsig +type Authorization struct { + scope [&Any] # The set of authorized links + s Varsig # Scope signed by the invoker } -type InvocationCapsule struct { - inv Invocation (rename "ucan/invoke@0.2.0") +type Invocation struct { + task &Task + auth &Authorization } -type Trace struct { +type InvocationCapsule union { + | Invocation ucan/invoke@0.2.0" +} representation keyed + +type Outcome struct { ran &Invocation # Invocation this is a receipt for out Result # Output of the invocation @@ -241,7 +246,7 @@ type Trace struct { } type Receipt struct { - trc Trace + ocm &Outcome sig Varsig } @@ -280,7 +285,7 @@ Using the JavaScript analogy from the introduction, a Task is similar to wrappin ```json { "uri" "mailto:alice@example.com", - "call": "msg/send", + "op": "msg/send", "input": { "to": [ "bob@example.com", @@ -308,11 +313,11 @@ Later, when we explore promise [pipelines], this also includes capturing the pro { "bafy...getMailingList": { "uri" "https://exmaple.com/mailinglist", - "call": "crud/read" + "op": "crud/read" }, "bafy...sendEmail": { "uri" "mailto://alice@example.com", - "call": "msg/send", + "op": "msg/send", "input": { "to": { "await/ok": { @@ -341,7 +346,7 @@ const sendEmail = msg.send("mailto://alice@example.com", { ```ipldsch type Task struct { uri URI - call Ability + op Ability input {String : Any} nnc String } @@ -351,11 +356,13 @@ type Task struct { ### 3.2.1 Resource -The `on` field MUST contain the [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) of the resource being accessed. If the resource being accessed is some static data, it is RECOMMENDED to reference it by the [`data`](https://en.wikipedia.org/wiki/Data_URI_scheme), [`ipfs`](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#native-urls), or [`magnet`](https://en.wikipedia.org/wiki/Magnet_URI_scheme) URI schemes. +FIXME + +The `uri` field MUST contain the [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) of the resource being accessed. If the resource being accessed is some static data, it is RECOMMENDED to reference it by the [`data`](https://en.wikipedia.org/wiki/Data_URI_scheme), [`ipfs`](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#native-urls), or [`magnet`](https://en.wikipedia.org/wiki/Magnet_URI_scheme) URI schemes. ### 3.2.3 Ability -The `call` field MUST contain a [UCAN Ability](https://github.com/ucan-wg/spec/#23-ability). This field can be thought of as the message or trait being sent to the resource. +The `op` field MUST contain a [UCAN Ability](https://github.com/ucan-wg/spec/#23-ability). This field can be thought of as the message or trait being sent to the resource. ### 3.2.4 Input @@ -383,7 +390,7 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { "uri" "https://example.com/blog/posts", - "call": "crud/create", + "op": "crud/create", "input": { "headers": { "content-type": "application/json" @@ -406,7 +413,7 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { "uri" "mailto:akiko@example.com", - "call": "msg/send", + "op": "msg/send", "input": { "to": [ "boris@example.com", @@ -423,7 +430,7 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { "uri" "data:application/wasm;base64,AHdhc21lci11bml2ZXJzYWwAAAAAAOAEAAAAAAAAAAD9e7+p/QMAkSAEABH9e8GowANf1uz///8UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAACAAAACoAAAAIAAAABAAAACsAAAAMAAAACAAAANz///8AAAAA1P///wMAAAAlAAAALAAAAAAAAAAUAAAA/Xu/qf0DAJHzDx/44wMBqvMDAqphAkC5YAA/1mACALnzB0H4/XvBqMADX9bU////LAAAAAAAAAAAAAAAAAAAAAAAAAAvVXNlcnMvZXhwZWRlL0Rlc2t0b3AvdGVzdC53YXQAAGFkZF9vbmUHAAAAAAAAAAAAAAAAYWRkX29uZV9mAAAADAAAAAAAAAABAAAAAAAAAAkAAADk////AAAAAPz///8BAAAA9f///wEAAAAAAAAAAQAAAB4AAACM////pP///wAAAACc////AQAAAAAAAAAAAAAAnP///wAAAAAAAAAAlP7//wAAAACM/v//iP///wAAAAABAAAAiP///6D///8BAAAAqP///wEAAACk////AAAAAJz///8AAAAAlP///wAAAACM////AAAAAIT///8AAAAAAAAAAAAAAAAAAAAAAAAAAET+//8BAAAAWP7//wEAAABY/v//AQAAAID+//8BAAAAxP7//wEAAADU/v//AAAAAMz+//8AAAAAxP7//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU////pP///wAAAAAAAQEBAQAAAAAAAACQ////AAAAAIj///8AAAAAAAAAAAAAAADQAQAAAAAAAA==", - "call": "wasm/run", + "op": "wasm/run", "input": { "func": "add_one", "input": [ @@ -571,7 +578,7 @@ type InvocationCapsule struct { { "bafy...createBlogPost": { "uri" "https://example.com/blog/posts", - "call": "crud/create", + "op": "crud/create", "input": { "headers": { "content-type": "application/json" @@ -622,7 +629,7 @@ type InvocationCapsule struct { { "bafy...createBlogPostTask": { "uri" "https://example.com/blog/posts", - "call": "crud/create", + "op": "crud/create", "input": { "headers": { "content-type": "application/json" @@ -640,7 +647,7 @@ type InvocationCapsule struct { }, "bafy...sendEmailTask": { "uri" "mailto:akiko@example.com", - "call": "msg/send", + "op": "msg/send", "input": { "to": [ "boris@example.com", @@ -673,7 +680,7 @@ type InvocationCapsule struct { { "bafy...updateDnsTask": { "uri" "dns:example.com?TYPE=TXT", - "call": "crud/update", + "op": "crud/update", "input": { "value": "hello world" } @@ -837,10 +844,10 @@ A `Receipt` is an attestation of the [Result] and requested [Effect]s by a [Task Receipts MUST use the same version as the invocation that they contain. -## 8.1 Trace +## 8.1 Response ```ipldsch -type Trace struct { +type Outcome struct { ran &Invocation # Invocation this is a receipt for out Result # Output of the invocation @@ -891,14 +898,14 @@ If OPTIONAL `prf` field is present, MUST contain link to UCAN delegation authori ```ipldsch type Receipt struct { - trc Trace + ocm Outcome sig Varsig } ``` -### 8.2.1 Trace +### 8.2.1 Outcome -The `trc` field MUST contain the `Trace` of the `Invocation` that the recept is for. +The `ocm` field MUST contain the `Outcome` of the `Invocation` that the recept is for. ### 8.2.2 Signature @@ -1033,7 +1040,7 @@ For example, consider the following invocation batch: { "bafy...createBlogPostTask": { "uri" "https://example.com/blog/posts", - "call": "crud/create", + "op": "crud/create", "input": { "payload": { "title": "How UCAN Tasks Changed My Life", @@ -1043,11 +1050,11 @@ For example, consider the following invocation batch: }, "bafy...getBlogEditorsTask": { "uri" "https://example.com/users/editors", - "call": "crud/read" + "op": "crud/read" }, "bafy...sendEmailTask": { "uri" "mailto:akiko@example.com", - "call": "msg/send", + "op": "msg/send", "input": { "to": { "await/ok": { @@ -1171,14 +1178,14 @@ flowchart BR { "bafy...updateDnsTask": { "uri" "dns:example.com?TYPE=TXT", - "call": "crud/update", + "op": "crud/update", "input": { "value": "hello world" } }, "bafy...sendBobEmailTask": { "uri" "mailto://alice@example.com", - "call": "msg/send", + "op": "msg/send", "input": { "to": "bob@example.com", "subject": "DNSLink for example.com", @@ -1191,7 +1198,7 @@ flowchart BR }, "bafy...sendCarolEmailTask": { "uri" "mailto://alice@example.com", - "call": "msg/send", + "op": "msg/send", "input": { "to": "carol@example.com", "subject": "Hey Carol, DNSLink was updated!", @@ -1204,7 +1211,7 @@ flowchart BR }, "bafy...updateReportTask": { "uri" "https://example.com/report", - "call": "crud/update", + "op": "crud/update", "input": { "payload": { "from": "mailto://alice@exmaple.com", @@ -1344,14 +1351,14 @@ flowchart TB { "bafy...updateDnsTask": { "uri" "dns:example.com?TYPE=TXT", - "call": "crud/update", + "op": "crud/update", "input": { "value": "hello world" } }, "bafy...sendBobEmailTask": { "uri" "mailto://alice@example.com", - "call": "msg/send", + "op": "msg/send", "input": { "to": "bob@example.com", "subject": "DNSLink for example.com", @@ -1412,7 +1419,7 @@ flowchart TB { "bafy...emailCarolTask": { "uri" "mailto://alice@example.com", - "call": "msg/send", + "op": "msg/send", "input": { "to": "carol@example.com", "subject": "Hey Carol, DNSLink was updated!", @@ -1425,7 +1432,7 @@ flowchart TB }, "bafy...updateReportTask": { "uri" "https://example.com/report", - "call": "crud/update", + "op": "crud/update", "input": { "payload": { "from": "mailto://alice@exmaple.com", @@ -1544,3 +1551,4 @@ Thanks to [Rod Vagg](https://github.com/rvagg/) for the clarifications on IPLD S [ucan-ipld]: https://github.com/ucan-wg/ucan-ipld/ [ucan]: https://github.com/ucan-wg/spec/ [varsig]: https://github.com/ChainAgnostic/varsig/ +[Haskell]: https://en.wikipedia.org/wiki/Haskell From ebcfaddae012fcb965d91d525f8ce797b2a1422f Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Fri, 24 Mar 2023 17:05:49 -0700 Subject: [PATCH 13/32] Typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c841404c..56525961 100644 --- a/README.md +++ b/README.md @@ -224,7 +224,7 @@ type Invocation struct { } type InvocationCapsule union { - | Invocation ucan/invoke@0.2.0" + | Invocation "ucan/invoke@0.2.0" } representation keyed type Outcome struct { From 9bedb28fca2d3e96743ec0832797af9b5daa5e29 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Mon, 27 Mar 2023 12:47:07 -0700 Subject: [PATCH 14/32] Update per conversations last week --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 56525961..096019a3 100644 --- a/README.md +++ b/README.md @@ -215,7 +215,7 @@ type Task struct { type Authorization struct { scope [&Any] # The set of authorized links - s Varsig # Scope signed by the invoker + auth Authorization # Scope signed by the invoker } type Invocation struct { @@ -247,7 +247,7 @@ type Outcome struct { type Receipt struct { ocm &Outcome - sig Varsig + auth &Authorization } type ReceiptCapsule struct { @@ -844,7 +844,7 @@ A `Receipt` is an attestation of the [Result] and requested [Effect]s by a [Task Receipts MUST use the same version as the invocation that they contain. -## 8.1 Response +## 8.1 Outcome ```ipldsch type Outcome struct { @@ -905,7 +905,7 @@ type Receipt struct { ### 8.2.1 Outcome -The `ocm` field MUST contain the `Outcome` of the `Invocation` that the recept is for. +The `ocm` field MUST contain the `Outcome` of the `Invocation` that the receipt is for. ### 8.2.2 Signature From 1cb5b44c1dbd4d397a26b113d9fe7a3d0d7cd030 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Tue, 28 Mar 2023 13:21:07 -0700 Subject: [PATCH 15/32] Fix schema --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 096019a3..0274c304 100644 --- a/README.md +++ b/README.md @@ -262,17 +262,17 @@ type Result union { # Represents a request to invoke enclosed set of tasks concurrently type Effects struct { # Primary set of tasks to be invoked - fork [&Task] + fork [&Instruction] # Continuation for straight-line programs - join optional &Task + join optional &Instruction } # Way to reference result of the Task type Await union { - | &Task "await/*" - | &Task "await/ok" - | &Task "await/error" + | &Instruction "await/*" + | &Instruction "await/ok" + | &Instruction "await/error" } representation keyed ``` From eb2422bda99f62d341e3f42cb94f07842beb7012 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Tue, 28 Mar 2023 14:04:51 -0700 Subject: [PATCH 16/32] "uri" -> "rsc" --- README.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 0274c304..1c928752 100644 --- a/README.md +++ b/README.md @@ -284,7 +284,7 @@ Using the JavaScript analogy from the introduction, a Task is similar to wrappin ```json { - "uri" "mailto:alice@example.com", + "rsc" "mailto:alice@example.com", "op": "msg/send", "input": { "to": [ @@ -312,11 +312,11 @@ Later, when we explore promise [pipelines], this also includes capturing the pro ```json { "bafy...getMailingList": { - "uri" "https://exmaple.com/mailinglist", + "rsc" "https://exmaple.com/mailinglist", "op": "crud/read" }, "bafy...sendEmail": { - "uri" "mailto://alice@example.com", + "rsc" "mailto://alice@example.com", "op": "msg/send", "input": { "to": { @@ -389,7 +389,7 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { - "uri" "https://example.com/blog/posts", + "rsc" "https://example.com/blog/posts", "op": "crud/create", "input": { "headers": { @@ -412,7 +412,7 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { - "uri" "mailto:akiko@example.com", + "rsc" "mailto:akiko@example.com", "op": "msg/send", "input": { "to": [ @@ -429,7 +429,7 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS ```json { - "uri" "data:application/wasm;base64,AHdhc21lci11bml2ZXJzYWwAAAAAAOAEAAAAAAAAAAD9e7+p/QMAkSAEABH9e8GowANf1uz///8UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAACAAAACoAAAAIAAAABAAAACsAAAAMAAAACAAAANz///8AAAAA1P///wMAAAAlAAAALAAAAAAAAAAUAAAA/Xu/qf0DAJHzDx/44wMBqvMDAqphAkC5YAA/1mACALnzB0H4/XvBqMADX9bU////LAAAAAAAAAAAAAAAAAAAAAAAAAAvVXNlcnMvZXhwZWRlL0Rlc2t0b3AvdGVzdC53YXQAAGFkZF9vbmUHAAAAAAAAAAAAAAAAYWRkX29uZV9mAAAADAAAAAAAAAABAAAAAAAAAAkAAADk////AAAAAPz///8BAAAA9f///wEAAAAAAAAAAQAAAB4AAACM////pP///wAAAACc////AQAAAAAAAAAAAAAAnP///wAAAAAAAAAAlP7//wAAAACM/v//iP///wAAAAABAAAAiP///6D///8BAAAAqP///wEAAACk////AAAAAJz///8AAAAAlP///wAAAACM////AAAAAIT///8AAAAAAAAAAAAAAAAAAAAAAAAAAET+//8BAAAAWP7//wEAAABY/v//AQAAAID+//8BAAAAxP7//wEAAADU/v//AAAAAMz+//8AAAAAxP7//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU////pP///wAAAAAAAQEBAQAAAAAAAACQ////AAAAAIj///8AAAAAAAAAAAAAAADQAQAAAAAAAA==", + "rsc" "data:application/wasm;base64,AHdhc21lci11bml2ZXJzYWwAAAAAAOAEAAAAAAAAAAD9e7+p/QMAkSAEABH9e8GowANf1uz///8UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAACAAAACoAAAAIAAAABAAAACsAAAAMAAAACAAAANz///8AAAAA1P///wMAAAAlAAAALAAAAAAAAAAUAAAA/Xu/qf0DAJHzDx/44wMBqvMDAqphAkC5YAA/1mACALnzB0H4/XvBqMADX9bU////LAAAAAAAAAAAAAAAAAAAAAAAAAAvVXNlcnMvZXhwZWRlL0Rlc2t0b3AvdGVzdC53YXQAAGFkZF9vbmUHAAAAAAAAAAAAAAAAYWRkX29uZV9mAAAADAAAAAAAAAABAAAAAAAAAAkAAADk////AAAAAPz///8BAAAA9f///wEAAAAAAAAAAQAAAB4AAACM////pP///wAAAACc////AQAAAAAAAAAAAAAAnP///wAAAAAAAAAAlP7//wAAAACM/v//iP///wAAAAABAAAAiP///6D///8BAAAAqP///wEAAACk////AAAAAJz///8AAAAAlP///wAAAACM////AAAAAIT///8AAAAAAAAAAAAAAAAAAAAAAAAAAET+//8BAAAAWP7//wEAAABY/v//AQAAAID+//8BAAAAxP7//wEAAADU/v//AAAAAMz+//8AAAAAxP7//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU////pP///wAAAAAAAQEBAQAAAAAAAACQ////AAAAAIj///8AAAAAAAAAAAAAAADQAQAAAAAAAA==", "op": "wasm/run", "input": { "func": "add_one", @@ -577,7 +577,7 @@ type InvocationCapsule struct { ```json { "bafy...createBlogPost": { - "uri" "https://example.com/blog/posts", + "rsc" "https://example.com/blog/posts", "op": "crud/create", "input": { "headers": { @@ -628,7 +628,7 @@ type InvocationCapsule struct { ```json { "bafy...createBlogPostTask": { - "uri" "https://example.com/blog/posts", + "rsc" "https://example.com/blog/posts", "op": "crud/create", "input": { "headers": { @@ -646,7 +646,7 @@ type InvocationCapsule struct { } }, "bafy...sendEmailTask": { - "uri" "mailto:akiko@example.com", + "rsc" "mailto:akiko@example.com", "op": "msg/send", "input": { "to": [ @@ -679,7 +679,7 @@ type InvocationCapsule struct { ```json { "bafy...updateDnsTask": { - "uri" "dns:example.com?TYPE=TXT", + "rsc" "dns:example.com?TYPE=TXT", "op": "crud/update", "input": { "value": "hello world" @@ -1039,7 +1039,7 @@ For example, consider the following invocation batch: ```json { "bafy...createBlogPostTask": { - "uri" "https://example.com/blog/posts", + "rsc" "https://example.com/blog/posts", "op": "crud/create", "input": { "payload": { @@ -1049,11 +1049,11 @@ For example, consider the following invocation batch: } }, "bafy...getBlogEditorsTask": { - "uri" "https://example.com/users/editors", + "rsc" "https://example.com/users/editors", "op": "crud/read" }, "bafy...sendEmailTask": { - "uri" "mailto:akiko@example.com", + "rsc" "mailto:akiko@example.com", "op": "msg/send", "input": { "to": { @@ -1177,14 +1177,14 @@ flowchart BR ```json { "bafy...updateDnsTask": { - "uri" "dns:example.com?TYPE=TXT", + "rsc" "dns:example.com?TYPE=TXT", "op": "crud/update", "input": { "value": "hello world" } }, "bafy...sendBobEmailTask": { - "uri" "mailto://alice@example.com", + "rsc" "mailto://alice@example.com", "op": "msg/send", "input": { "to": "bob@example.com", @@ -1197,7 +1197,7 @@ flowchart BR } }, "bafy...sendCarolEmailTask": { - "uri" "mailto://alice@example.com", + "rsc" "mailto://alice@example.com", "op": "msg/send", "input": { "to": "carol@example.com", @@ -1210,7 +1210,7 @@ flowchart BR } }, "bafy...updateReportTask": { - "uri" "https://example.com/report", + "rsc" "https://example.com/report", "op": "crud/update", "input": { "payload": { @@ -1350,14 +1350,14 @@ flowchart TB ```json { "bafy...updateDnsTask": { - "uri" "dns:example.com?TYPE=TXT", + "rsc" "dns:example.com?TYPE=TXT", "op": "crud/update", "input": { "value": "hello world" } }, "bafy...sendBobEmailTask": { - "uri" "mailto://alice@example.com", + "rsc" "mailto://alice@example.com", "op": "msg/send", "input": { "to": "bob@example.com", @@ -1418,7 +1418,7 @@ flowchart TB ```json { "bafy...emailCarolTask": { - "uri" "mailto://alice@example.com", + "rsc" "mailto://alice@example.com", "op": "msg/send", "input": { "to": "carol@example.com", @@ -1431,7 +1431,7 @@ flowchart TB } }, "bafy...updateReportTask": { - "uri" "https://example.com/report", + "rsc" "https://example.com/report", "op": "crud/update", "input": { "payload": { From 0cbdedb12dc682f0b13051ce943c4eae336a795f Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Tue, 28 Mar 2023 16:59:15 -0700 Subject: [PATCH 17/32] Update multiple fields --- README.md | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 1c928752..bc722d7c 100644 --- a/README.md +++ b/README.md @@ -209,17 +209,17 @@ type Task struct { meta {String : Any} prf [&UCAN] - # Receipt of the invocation that caused this invocation - cause optional &Invocation + # Receipt of the invocation that caused this Task to be run + cause optional &Instruction } type Authorization struct { scope [&Any] # The set of authorized links - auth Authorization # Scope signed by the invoker + s Varsig # Scope signed by the invoker } type Invocation struct { - task &Task + task Task auth &Authorization } @@ -246,8 +246,8 @@ type Outcome struct { } type Receipt struct { - ocm &Outcome - auth &Authorization + ocm Outcome + sig Varsig } type ReceiptCapsule struct { @@ -358,7 +358,7 @@ type Task struct { FIXME -The `uri` field MUST contain the [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) of the resource being accessed. If the resource being accessed is some static data, it is RECOMMENDED to reference it by the [`data`](https://en.wikipedia.org/wiki/Data_URI_scheme), [`ipfs`](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#native-urls), or [`magnet`](https://en.wikipedia.org/wiki/Magnet_URI_scheme) URI schemes. +The `rsc` field MUST contain the [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) of the resource being accessed. If the resource being accessed is some static data, it is RECOMMENDED to reference it by the [`data`](https://en.wikipedia.org/wiki/Data_URI_scheme), [`ipfs`](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#native-urls), or [`magnet`](https://en.wikipedia.org/wiki/Magnet_URI_scheme) URI schemes. ### 3.2.3 Ability @@ -450,11 +450,8 @@ An [Authorization] is cryptographically signed data set. It represents an author ```ipldsch type Authorization struct { - # Authorization is denoted by the set of links been authorized - scope [&Any] - - # Scope signed by the invoker - s VarSig + sc ope [&Any] # Authorization is denoted by the set of links been authorized + s Varsig # Scope signed by the invoker } ``` @@ -475,18 +472,10 @@ The `s` field MUST contain a [Varsig] of the [CBOR] encoded `scope` field. ```json { "scope": [ - { - "/": "bafyreihtmwju3okftpeuqe3x3ux5e7c2jescakwnoiyv45vnicke4kdxy4" - }, - { - "/": "bafyreieuo63r3y2nuycaq4b3q2xvco3nprlxiwzcfp4cuupgaywat3z6mq" - } + {"/": "bafyreihtmwju3okftpeuqe3x3ux5e7c2jescakwnoiyv45vnicke4kdxy4"}, + {"/": "bafyreieuo63r3y2nuycaq4b3q2xvco3nprlxiwzcfp4cuupgaywat3z6mq"} ], - "s": { - "/": { - "bytes": "7aEDQIJB8XXJ6hWbwu40fN4bq8+Zq8BxyybSWXatMVU3VsL+yzVYpeJqsEBQE5rNtUJefR5rRCNimKNZMJjA9/udZQQ" - } - } + "s": {"/": {"bytes": "7aEDQIJB8XXJ6hWbwu40fN4bq8+Zq8BxyybSWXatMVU3VsL+yzVYpeJqsEBQE5rNtUJefR5rRCNimKNZMJjA9/udZQQ"}} } ``` From 60bebfa2687a9be24d1f2a8c26aeec0231932479 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Tue, 28 Mar 2023 17:02:01 -0700 Subject: [PATCH 18/32] Receipt it is! --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc722d7c..ec97ac20 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,7 @@ type Task struct { prf [&UCAN] # Receipt of the invocation that caused this Task to be run - cause optional &Instruction + cause optional &Receipt } type Authorization struct { From 1b87de8aa92251e0516e5508ec9c8a74a070db26 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Wed, 29 Mar 2023 23:24:41 -0700 Subject: [PATCH 19/32] Update README.md Co-authored-by: Irakli Gozalishvili Signed-off-by: Brooklyn Zelenka --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ec97ac20..5ad839f8 100644 --- a/README.md +++ b/README.md @@ -250,9 +250,9 @@ type Receipt struct { sig Varsig } -type ReceiptCapsule struct { - rct Receipt (rename "ucan/receipt@0.2.0") -} +type ReceiptCapsule union { + | Receipt "ucan/receipt@0.2.0" +} representation keyed type Result union { | any "ok" # Success From 3e802ee5a8ff18bef81e7022e4703e9a5d0fca64 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Wed, 29 Mar 2023 23:32:51 -0700 Subject: [PATCH 20/32] Keep updating with latest naming --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 5ad839f8..145957a9 100644 --- a/README.md +++ b/README.md @@ -345,7 +345,7 @@ const sendEmail = msg.send("mailto://alice@example.com", { ```ipldsch type Task struct { - uri URI + rsc URI op Ability input {String : Any} nnc String @@ -487,11 +487,11 @@ The `auth` field MUST be contain an [Authorization] which signs over the `&Task` Concretely, this means that the `&Task` MUST be present in the associated `auth`'s `scope` field. An `Invocation` where the associated [Authorization] does not include the [Task] in the `scope` MUST be considered invalid. -## 5.1 Context +## 5.1 Task -```ipldsch +```Task type Context struct { - run &Task + run &Instruction meta {String : Any} prf [&UCAN] @@ -500,7 +500,7 @@ type Context struct { } ``` -### 5.1.1 Task +### 5.1.1 Instruction The `run` field MUST contain a link to the [Task] to be run. @@ -514,7 +514,7 @@ If `meta` field is not present, it is implicitly a `unit` represented as an empt The `prf` field MUST contain links to any UCANs that provide the authority to perform this task. All of the outermost proofs MUST have `aud` field set to the [Executor]'s DID. All of the outmost proofs MUST have `iss` field set to the [Invoker]'s DID. -### 5.1.4 Cause +### 5.1.4 Optional Cause [Task]s MAY be invoked as an effect caused by a prior [Invocation]. Such [Invocation]s SHOULD have a `cause` field set to the [Receipt] link of the [Invocation] that caused it. The linked [Receipt] MUST have an `Effect` (the `fx` field) containing invoked [Task] in the `run` field. @@ -524,27 +524,27 @@ An `Invocation` is a signed `Context`. ```ipldsch type Invocation struct { - ctx Context - sig Varsig + task Task + auth &Authorization } ``` -### 5.2.1 Context +### 5.2.1 Task -The `Context` containing the `Task` and any configuration. +The `Task` containing the `Instruction` and any configuration. -### 5.2.2 Signature +### 5.2.2 Authorization -The `sig` field MUST contain a [varsig] of the `Context`, signed by the issuer of the proofs. +The `auth` field MUST contain a [varsig] signing over an array of CIDs that includes the `Task`'s CID, signed by the issuer of the proofs. ## 5.3 Capsule An invocation capsule associates the `Invocation` with a versioned schema. This MAY be omitted in contexts where the schema and version are clear from context (for example, when nested in another structure that defines the version) ```ipldsch -type InvocationCapsule struct { - inv Invocation (rename "ucan/invoke@0.2.0") -} +type InvocationCapsule union { + | Invocation "ucan/invoke@0.2.0" +} representation keyed ``` ## 5.4 DAG-JSON Example From 871aeae2b4663c80669363611be9346404188233 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Wed, 29 Mar 2023 23:45:49 -0700 Subject: [PATCH 21/32] Remove embedded versions in examples --- README.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/README.md b/README.md index 145957a9..6b695511 100644 --- a/README.md +++ b/README.md @@ -596,7 +596,6 @@ type InvocationCapsule union { } }, "bafy...invocation": { - "v": "0.1.0", "run": { "/": "bafy...createBlogPost" }, @@ -687,7 +686,6 @@ type InvocationCapsule union { } }, "bafy...updateDnsInvocation": { - "v": "0.1.0", "run": { "/": "bafy...updateDnsTask" }, @@ -1246,7 +1244,6 @@ flowchart BR } }, "bafy...updateDnsInvocation": { - "v": "0.1.0", "run": { "/": "bafy...updateDnsTask" }, @@ -1260,7 +1257,6 @@ flowchart BR ] }, "bafy...sendBobEmailInvocation": { - "v": "0.1.0", "run": { "/": "bafy...sendBobEmailTask" }, @@ -1274,7 +1270,6 @@ flowchart BR ] }, "bafy...sendCarolEmailInvocation": { - "v": "0.1.0", "run": { "/": "bafy...sendCarolEmailTask" }, @@ -1288,7 +1283,6 @@ flowchart BR ] }, "bafy...updateReportInvocation": { - "v": "0.1.0", "run": { "/": "bafy...updateReportTask" }, @@ -1359,7 +1353,6 @@ flowchart TB } }, "bafy...updateDnsInvocation": { - "v": "0.1.0", "run": { "/": "bafy...updateDnsInvocation" }, @@ -1373,7 +1366,6 @@ flowchart TB ] }, "bafy...sendBobEmailInvocation": { - "v": "0.1.0", "run": { "/": "bafy...sendBobEmailTask" }, @@ -1461,7 +1453,6 @@ flowchart TB } }, "bafy...emailCarolInvocation": { - "v": "0.1.0", "run": { "/": "bafy...emailCarolTask" }, @@ -1475,7 +1466,6 @@ flowchart TB ] }, "bafy...updateReportInvocation": { - "v": "0.1.0", "run": { "/": "bafy...updateReporttask" }, From 6a11a31e22107a904ce0f2909bb998571400de6c Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 30 Mar 2023 00:16:16 -0700 Subject: [PATCH 22/32] Continue updating to new format --- README.md | 68 +++++++++++++++++-------------------------------------- 1 file changed, 21 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 6b695511..c743864e 100644 --- a/README.md +++ b/README.md @@ -450,7 +450,7 @@ An [Authorization] is cryptographically signed data set. It represents an author ```ipldsch type Authorization struct { - sc ope [&Any] # Authorization is denoted by the set of links been authorized + scope [&Any] # Authorization is denoted by the set of links been authorized s Varsig # Scope signed by the invoker } ``` @@ -584,29 +584,15 @@ type InvocationCapsule union { } }, "bafy...auth": { - "scope": [ - { - "/": "bafy...createBlogPost" - } - ], - "s": { - "/": { - "bytes": "7aEDQPPhXNvtVb5/T+O40xXU6TSgJZDFnlVaV3GMlaEo/dvxtyaCLm8uUsFK4xzQsQd82QQUYA6fK506XqjghRlucAQ" - } - } + "scope": [{"/": "bafy...createBlogPostTask"}], + "s": {"/": {"bytes": "7aEDQPPhXNvtVb5/T+O40xXU6TSgJZDFnlVaV3GMlaEo/dvxtyaCLm8uUsFK4xzQsQd82QQUYA6fK506XqjghRlucAQ"}} }, "bafy...invocation": { - "run": { - "/": "bafy...createBlogPost" + "task": { + "run": {"/": "bafy...createBlogPost"}, + "prf": [{"/": "bafy...ucanProof"}] }, - "auth": { - "/": "bafy...auth" - }, - "prf": [ - { - "/": "bafy...ucanProof" - } - ] + "auth": {"/": "bafy...auth"} } } ``` @@ -646,16 +632,18 @@ type InvocationCapsule union { } }, "bafy...createBlogPostInvocation": { - "ctx": { + "task": { "run": {"/": "bafy...createBlogPostTask"}, "prf": [{"/": "bafyreid6q7uslc33xqvodeysekliwzs26u5wglas3u4ndlzkelolbt5z3a"}] }, "sig": {"/": "bafy...multipleAuth"} }, "bafy...sendEmailInvocation": { - "ctx": { + "task": { "run": {"/": "bafy...sendEmailTask"}, - "prf": [{"/": "bafyreihvee5irbkfxspsim5s2zk2onb7hictmpbf5lne2nvq6xanmbm6e4"}] + "prf": [ + {"/": "bafyreihvee5irbkfxspsim5s2zk2onb7hictmpbf5lne2nvq6xanmbm6e4"} + ] }, "sig": {"/": "bafy...multipleAuth"}, } @@ -675,30 +663,16 @@ type InvocationCapsule union { }, "bafy...auth": { "scope": [ - { - "/": "bafyreievhy7rnzot7mnzbnqtiajhxx7fyn7y2wkjtuzwtmnflty3767dny" - } + {"/": "bafyreievhy7rnzot7mnzbnqtiajhxx7fyn7y2wkjtuzwtmnflty3767dny"} ], - "s": { - "/": { - "bytes": "7aEDQIscUKVuAIB2Yj6jdX5ru9OcnQLxLutvHPjeMD3pbtHIoErFpo7OoC79Oe2ShgQMLbo2e6dvHh9scqHKEOmieA0" - } - } + "s": {"/": { "bytes": "7aEDQIscUKVuAIB2Yj6jdX5ru9OcnQLxLutvHPjeMD3pbtHIoErFpo7OoC79Oe2ShgQMLbo2e6dvHh9scqHKEOmieA0"}} }, "bafy...updateDnsInvocation": { - "run": { - "/": "bafy...updateDnsTask" - }, - "auth": { - "/": "bafy...auth" - }, - "cause": { - "/": "bafy...somePriorInvocation" - }, + "run": {"/": "bafy...updateDnsTask"}, + "auth": {"/": "bafy...auth"}, + "cause": {"/": "bafy...somePriorInvocation"}, "prf": [ - { - "/": "bafyreieynwqrabzdhgl652ftsk4mlphcj3bxchkj2aw5eb6dc2wxieilau" - } + {"/": "bafyreieynwqrabzdhgl652ftsk4mlphcj3bxchkj2aw5eb6dc2wxieilau"} ] } } @@ -1107,9 +1081,9 @@ An `Await` describes the eventual output of the referenced [Task] invocation. An ```ipldsch type Await union { - | &Task "await/*" - | &Task "await/ok" - | &Task "await/error" + | &Instruction "await/*" + | &Instruction "await/ok" + | &Instruction "await/error" } representation keyed ``` From 5362df38f54bed923d04a4c0d5c2fa2181fee1c0 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Fri, 31 Mar 2023 20:39:21 -0700 Subject: [PATCH 23/32] Receipt capsule has pointer not inlined --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c743864e..5b42ba8c 100644 --- a/README.md +++ b/README.md @@ -251,7 +251,7 @@ type Receipt struct { } type ReceiptCapsule union { - | Receipt "ucan/receipt@0.2.0" + | &Receipt "ucan/receipt@0.2.0" } representation keyed type Result union { From d218fecde0227adbcffcdf56a6eb397967b8dd25 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Wed, 5 Apr 2023 14:47:20 -0700 Subject: [PATCH 24/32] Update prose & bring in line with top-level schema --- README.md | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 5b42ba8c..09bee343 100644 --- a/README.md +++ b/README.md @@ -250,7 +250,7 @@ type Receipt struct { sig Varsig } -type ReceiptCapsule union { +type ReceiptTag union { | &Receipt "ucan/receipt@0.2.0" } representation keyed @@ -276,11 +276,11 @@ type Await union { } representation keyed ``` -# 3 Task +# 3 Instruction -A Task is the smallest unit of work that can be requested from a UCAN. It describes one `(resource, ability, input)` triple. The `input` field is free form, and depend on the specific resource and ability being interacted with, and is not described in this specification. +An Instruction is the smallest unit of work that can be requested from a UCAN. It describes one `(resource, operation, input)` triple. The `input` field is free form, and depend on the specific resource and ability being interacted with, and is not described in this specification. -Using the JavaScript analogy from the introduction, a Task is similar to wrapping a call in an anonymous function: +Using the JavaScript analogy from the introduction, an Instructon is similar to wrapping a call in a closure: ```json { @@ -307,7 +307,7 @@ Using the JavaScript analogy from the introduction, a Task is similar to wrappin }) ``` -Later, when we explore promise [pipelines], this also includes capturing the promise: +Later, when we explore promise [pipelines], this also includes capturing the promise, also with a natural analogy to closures: ```json { @@ -356,8 +356,6 @@ type Task struct { ### 3.2.1 Resource -FIXME - The `rsc` field MUST contain the [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) of the resource being accessed. If the resource being accessed is some static data, it is RECOMMENDED to reference it by the [`data`](https://en.wikipedia.org/wiki/Data_URI_scheme), [`ipfs`](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#native-urls), or [`magnet`](https://en.wikipedia.org/wiki/Magnet_URI_scheme) URI schemes. ### 3.2.3 Ability @@ -442,8 +440,6 @@ If present, the OPTIONAL `nnc` field MUST include a random nonce expressed in AS # 4 Authorization -// FIXME? - An [Authorization] is cryptographically signed data set. It represents an authorization to run [Task]s that are included in `scope` data set. ## 4.1 Schema @@ -479,24 +475,24 @@ The `s` field MUST contain a [Varsig] of the [CBOR] encoded `scope` field. } ``` -# 5 Invocation +# 5 Task As [noted in the introduction][lazy-vs-eager], there is a difference between a reference to a function and calling that function. The [Invocation] is an instruction to the [Executor] to perform enclosed [Task]. [Invocation]s are not executable until they have been provided provable authority (in form of UCANs in the `prf` field) and an [Authorization] (in the `auth` field) from the [Invoker]. The `auth` field MUST be contain an [Authorization] which signs over the `&Task` in `run`. -Concretely, this means that the `&Task` MUST be present in the associated `auth`'s `scope` field. An `Invocation` where the associated [Authorization] does not include the [Task] in the `scope` MUST be considered invalid. +Concretely, this means that the `&Task` MUST be present in the associated `auth`'s `scope` field. A `Receipt` where the associated [Authorization] does not include the [Task] in the `scope` MUST be considered invalid. ## 5.1 Task -```Task -type Context struct { +```ipldsch +type Task struct { run &Instruction meta {String : Any} prf [&UCAN] # Receipt of the invocation that caused this invocation - cause optional &Invocation + cause optional &Receipt } ``` @@ -542,7 +538,7 @@ The `auth` field MUST contain a [varsig] signing over an array of CIDs that incl An invocation capsule associates the `Invocation` with a versioned schema. This MAY be omitted in contexts where the schema and version are clear from context (for example, when nested in another structure that defines the version) ```ipldsch -type InvocationCapsule union { +type InvocationTag union { | Invocation "ucan/invoke@0.2.0" } representation keyed ``` @@ -875,7 +871,7 @@ The `sig` field MUST contain a [Varsig] of the [DAG-CBOR] encoded Receipt withou ## 8.3 Capsule ```ipldsch -type ReceiptCapsule struct { +type ReceiptTag struct { rct Receipt (rename "ucan/receipt@0.2.0") } ``` From 2f8a779ee9b823d13de1e1f031271aba032dbb7e Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Wed, 5 Apr 2023 15:03:39 -0700 Subject: [PATCH 25/32] update per varsig (remove one level of nesting) --- README.md | 61 +++++++++++++++++++++---------------------------------- 1 file changed, 23 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 09bee343..411928d3 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ - [Brooklyn Zelenka](https://github.com/expede/), [Fission](https://fission.codes/) - [Irakli Gozalishvili](https://github.com/Gozala), [DAG House](https://dag.house/) +- [Zeeshan Lakhani](https://github.com/zeeshanlakhani), [Fission](https://fission.codes/) ## Depends On @@ -223,11 +224,11 @@ type Invocation struct { auth &Authorization } -type InvocationCapsule union { +type InvocationTag union { | Invocation "ucan/invoke@0.2.0" } representation keyed -type Outcome struct { +type Receipt struct { ran &Invocation # Invocation this is a receipt for out Result # Output of the invocation @@ -243,13 +244,10 @@ type Outcome struct { # delegation chain from executor to the issuer. This should be # omitted when the executor is the issuer. prf [&UCAN] -} -type Receipt struct { - ocm Outcome sig Varsig } - + type ReceiptTag union { | &Receipt "ucan/receipt@0.2.0" } representation keyed @@ -533,9 +531,9 @@ The `Task` containing the `Instruction` and any configuration. The `auth` field MUST contain a [varsig] signing over an array of CIDs that includes the `Task`'s CID, signed by the issuer of the proofs. -## 5.3 Capsule +## 5.3 Invocation Tag -An invocation capsule associates the `Invocation` with a versioned schema. This MAY be omitted in contexts where the schema and version are clear from context (for example, when nested in another structure that defines the version) +An invocation capsule associates the `Invocation` with a versioned schema. This field is NOT REQUIRED. Wrapping an `Invocation` in an `InvocationTag` is RECOMMENDED in contexts where the schema and version are not clear from context, such as when it is being stores or passed around without being nested in another structure that defines the version in its schema. ```ipldsch type InvocationTag union { @@ -801,7 +799,7 @@ A `Receipt` is an attestation of the [Result] and requested [Effect]s by a [Task Receipts MUST use the same version as the invocation that they contain. -## 8.1 Outcome +## 8.1 Receipt ```ipldsch type Outcome struct { @@ -820,6 +818,8 @@ type Outcome struct { # delegation chain from executor to the issuer. This should be # omitted when the executor is the issuer. prf [&UCAN] + + sig Varsig } ``` @@ -851,36 +851,23 @@ If `iss` field is omitted, Receipt MUST be signed by the [Executor]. If OPTIONAL `prf` field is present, MUST contain link to UCAN delegation authorizing Receipt Issuer (`iss`) to carry [Task] execution. -## 8.2 Receipt - -```ipldsch -type Receipt struct { - ocm Outcome - sig Varsig -} -``` - -### 8.2.1 Outcome - -The `ocm` field MUST contain the `Outcome` of the `Invocation` that the receipt is for. - -### 8.2.2 Signature +### 8.1.7 Signature The `sig` field MUST contain a [Varsig] of the [DAG-CBOR] encoded Receipt without `s` field. The signature MUST be generated by the [Executor] or a delegate if OPTIONAL `iss` field is set. -## 8.3 Capsule +## 8.2 Receipt Tag ```ipldsch -type ReceiptTag struct { - rct Receipt (rename "ucan/receipt@0.2.0") -} +type ReceiptTag union { + | &Receipt "ucan/receipt@0.2.0" +} representation keyed ``` -A receipt capsule associates the `Receipt` with a versioned schema. This MAY be omitted in contexts where the schema and version are clear from context (for example, when nested in another structure that defines the version). +A Receipt Tag associates the `Receipt` with a versioned schema. This MAY be omitted in contexts where the schema and version are clear from context (for example, when nested in another structure that defines the version). -## 8.4 DAG-JSON Examples +## 8.3 DAG-JSON Examples -### 8.4.1 Issued by Executor +### 8.3.1 Issued by Executor ```json { @@ -910,7 +897,7 @@ A receipt capsule associates the `Receipt` with a versioned schema. This MAY be } ``` -### 8.4.2 Issued by Delegate +### 8.3.2 Issued by Delegate ```json { @@ -946,7 +933,7 @@ A receipt capsule associates the `Receipt` with a versioned schema. This MAY be } ``` -### 8.4.3 Receipt with effects +### 8.3.3 Receipt with effects ```json { @@ -1065,7 +1052,7 @@ const notify = msg.send("mailto:akiko@example.com", { }) ``` -Any [Task] field other besides `do` MAY be substituted with `Await`. The `do` field is critical in understanding what kind of action will be performed and CAN NOT be substituted with `Await`. +Any [Task] field other besides `op` MAY be substituted with `Await`. The `op` field is critical in understanding what kind of action will be performed and CAN NOT be substituted with `Await`. An [Await] MAY be used across [Invocation]s with a same [Authorization], or across [Invocation]s with different [Authorization] and MAY even be across multiple Invokers and Executors. As long as the invocation can be resolved, it MAY be promised. This is sometimes referred to as ["promise pipelining"](http://erights.org/elib/distrib/pipeline.html). @@ -1087,11 +1074,11 @@ type Await union { ##### 9.2.1 Success -The successful output of the [Task] MAY be referenced by wrapping the [Task] in the `"await/ok"` tag. +The successful output of the [Instruction] MAY be referenced by wrapping the [Instruction] in the `"await/ok"` tag. -[Executor] MUST fail [Task] that `Await`s successful output of the failed [Task]. +The [Executor] MUST fail an [Instruction] that `Await`s successful output of the failed [Instruction]. -[Executor] MUST substitute [Task] field set to the [Await] of the successful [Task] with an (unwrapped) `ok` value of the output. +Upon learning of a successful execution of an awaited `Instruction`, the [Executor] MUST substitute the [Instruction] field set with the (unwrapped) `ok` value of the output. ##### 9.2.2 Failure @@ -1469,8 +1456,6 @@ Many thanks to [Mark Miller](https://github.com/erights) for his [pioneering wor Many thanks to [Luke Marsen](https://github.com/lukemarsden) and [Simon Worthington](https://github.com/simonwo) for their feedback on invocation model from their work on [Bacalhau](https://www.bacalhau.org/) and [IPVM](https://github.com/ipvm-wg). -Many thanks to [Zeeshan Lakhani](https://github.com/zeeshanlakhani) for his many suggestions, references, clarifications, and suggestions on how to restructure sections for clarity. - Thanks to [Marc-Antoine Parent](https://github.com/maparent) for his discussions of the distinction between declarations and directives both in and out of a UCAN context. Many thanks to [Quinn Wilton](https://github.com/QuinnWilton) for her discussion of speech acts, the dangers of signing canonicalized data, and ergonomics. From ce0f9f8576c7c4773455e4302eb404e194796b83 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 6 Apr 2023 11:27:19 -0700 Subject: [PATCH 26/32] Update examples --- README.md | 71 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 411928d3..f18c1c3c 100644 --- a/README.md +++ b/README.md @@ -559,6 +559,20 @@ type InvocationTag union { ```json { + "_": { + "ucan/invocation@0.2.0": "bafy...invocation" + }, + "bafy...invocation": { + "task": { + "run": {"/": "bafy...createBlogPost"}, + "prf": [{"/": "bafy...ucanProof"}] + }, + "auth": {"/": "bafy...auth"} + }, + "bafy...auth": { + "scope": [{"/": "bafy...createBlogPostTask"}], + "s": {"/": {"bytes": "7aEDQPPhXNvtVb5/T+O40xXU6TSgJZDFnlVaV3GMlaEo/dvxtyaCLm8uUsFK4xzQsQd82QQUYA6fK506XqjghRlucAQ"}} + }, "bafy...createBlogPost": { "rsc" "https://example.com/blog/posts", "op": "crud/create", @@ -576,17 +590,6 @@ type InvocationTag union { "draft": true } } - }, - "bafy...auth": { - "scope": [{"/": "bafy...createBlogPostTask"}], - "s": {"/": {"bytes": "7aEDQPPhXNvtVb5/T+O40xXU6TSgJZDFnlVaV3GMlaEo/dvxtyaCLm8uUsFK4xzQsQd82QQUYA6fK506XqjghRlucAQ"}} - }, - "bafy...invocation": { - "task": { - "run": {"/": "bafy...createBlogPost"}, - "prf": [{"/": "bafy...ucanProof"}] - }, - "auth": {"/": "bafy...auth"} } } ``` @@ -595,7 +598,7 @@ type InvocationTag union { ```json { - "bafy...createBlogPostTask": { + "bafy...createBlogPostInstruction": { "rsc" "https://example.com/blog/posts", "op": "crud/create", "input": { @@ -613,7 +616,7 @@ type InvocationTag union { } } }, - "bafy...sendEmailTask": { + "bafy...sendEmailInstruction": { "rsc" "mailto:akiko@example.com", "op": "msg/send", "input": { @@ -625,14 +628,14 @@ type InvocationTag union { "subject": "Coffee" } }, - "bafy...createBlogPostInvocation": { + "bafy...createBlogPostTask": { "task": { "run": {"/": "bafy...createBlogPostTask"}, "prf": [{"/": "bafyreid6q7uslc33xqvodeysekliwzs26u5wglas3u4ndlzkelolbt5z3a"}] }, "sig": {"/": "bafy...multipleAuth"} }, - "bafy...sendEmailInvocation": { + "bafy...sendEmailTask": { "task": { "run": {"/": "bafy...sendEmailTask"}, "prf": [ @@ -640,7 +643,21 @@ type InvocationTag union { ] }, "sig": {"/": "bafy...multipleAuth"}, - } + }, + "bafy...sendEmailInvocation": { + "task": {"/": "bafy...sendEmailTask"}, + "auth": {"/": "bafy...multipleAuth"} + }, + "bafy...createBlogPostInvocation": { + "task": {"/": "bafy...createBlogPostTask"}, + "auth": {"/": "bafy...multipleAuth"} + }, + "bafy...multipleAuth": { + "scope": [ + {"/": "bafy...createBlogPostTask"}, + {"/": "bafy...sendEmailTask"} + ], + "s": {"/": {"bytes": "7aEDQKxIrga+88HNDd69Ho4Ggz8zkf+GxWC6dAGYua6l85YgiL3NqGxyGAygiSZtWrWUo6SokgOys2wYE7N+novtcwo"}} } ``` @@ -648,27 +665,31 @@ type InvocationTag union { ```json { - "bafy...updateDnsTask": { + "bafy...updateDnsInstruction": { "rsc" "dns:example.com?TYPE=TXT", "op": "crud/update", "input": { "value": "hello world" } }, - "bafy...auth": { - "scope": [ - {"/": "bafyreievhy7rnzot7mnzbnqtiajhxx7fyn7y2wkjtuzwtmnflty3767dny"} - ], - "s": {"/": { "bytes": "7aEDQIscUKVuAIB2Yj6jdX5ru9OcnQLxLutvHPjeMD3pbtHIoErFpo7OoC79Oe2ShgQMLbo2e6dvHh9scqHKEOmieA0"}} - }, - "bafy...updateDnsInvocation": { + "bafy...updateDnsTask": { "run": {"/": "bafy...updateDnsTask"}, "auth": {"/": "bafy...auth"}, "cause": {"/": "bafy...somePriorInvocation"}, "prf": [ {"/": "bafyreieynwqrabzdhgl652ftsk4mlphcj3bxchkj2aw5eb6dc2wxieilau"} ] - } + }, + "bafy...updateDnsInvocation": { + "task": {"/": "bafy...updateDnsTask"}, + "auth": {"/": "bafy...auth"} + }, + "bafy...auth": { + "scope": [ + {"/": "bafyreievhy7rnzot7mnzbnqtiajhxx7fyn7y2wkjtuzwtmnflty3767dny"} + ], + "s": {"/": { "bytes": "7aEDQIscUKVuAIB2Yj6jdX5ru9OcnQLxLutvHPjeMD3pbtHIoErFpo7OoC79Oe2ShgQMLbo2e6dvHh9scqHKEOmieA0"}} + }, } ``` From 46599e00a4cb6a9f3d7dd22b51e461a34486aa40 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 6 Apr 2023 11:38:17 -0700 Subject: [PATCH 27/32] Fix some internal links --- README.md | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index f18c1c3c..4d00da65 100644 --- a/README.md +++ b/README.md @@ -168,9 +168,13 @@ The executor MUST be the UCAN delegate. Their DID MUST be set the in `aud` field ## 2.2 Components -### 2.2.1 Task +### 2.2.1 Instruction -A [Task] is like a deferred function application: a request to perform some action on a resource with specific input. +An [Instruction] is like a deferred function application: a request to perform some action on a resource with specific input. + +### 2.2.2 Task + +A [Task] wraps an [Instruction] with runtime configuration, including timeouts, fuel, trace metadata, and so on. ### 2.2.2 Authorization @@ -178,11 +182,11 @@ An [Authorization] is a cryptographically signed proof permitting execution of r ### 2.2.3 Invocation -An [Invocation] is a command to the [Executor] to run the [Task], authorized by the [Invoker]. +An [Invocation] is an [Authorized] [Task]. ### 2.2.4 Result -A [Result] is the output of a [Task]. +A [Result] is the output of an [Instruction]. ### 2.2.5 Receipt @@ -1489,21 +1493,22 @@ Thanks to [Christine Lemmer-Webber](https://github.com/cwebber) for the many con Thanks to [Rod Vagg](https://github.com/rvagg/) for the clarifications on IPLD Schema implicits and the general IPLD worldview. -[authorization]: #4-authorization -[await]: #await +[Authorization]: #4-authorization +[Await]: #await +[Effect]: #7-effect +[Executor]: #212-executor +[Haskell]: https://en.wikipedia.org/wiki/Haskell +[Instruction]: #3-instruction +[Invocation]: #5-invocation +[Invoker]: #211-invoker +[Pipeline]: #9-pipelines +[Receipt]: #8-receipt +[Result]: #6-result +[Task]: #5-task +[UCAN]: https://github.com/ucan-wg/spec/ +[Varsig]: https://github.com/ChainAgnostic/varsig/ [dag-cbor]: https://ipld.io/specs/codecs/dag-cbor/spec/ [dag-json]: https://ipld.io/docs/codecs/known/dag-json/ -[effect]: #7-effect -[executor]: #212-executor -[invocation]: #5-invocation -[invoker]: #211-invoker [ipld representation]: https://ipld.io/docs/schemas/features/representation-strategies/ [lazy-vs-eager]: #112-lazy-vs-eager-evaluation -[pipelines]: #9-pipelines -[receipt]: #8-receipt -[result]: #6-result -[task]: #3-task [ucan-ipld]: https://github.com/ucan-wg/ucan-ipld/ -[ucan]: https://github.com/ucan-wg/spec/ -[varsig]: https://github.com/ChainAgnostic/varsig/ -[Haskell]: https://en.wikipedia.org/wiki/Haskell From 02d2ecdf132dad9fee3a9e1845857a7410c0fad1 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 6 Apr 2023 11:39:16 -0700 Subject: [PATCH 28/32] Spelling --- README.md | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 4d00da65..dbdc7b0d 100644 --- a/README.md +++ b/README.md @@ -282,7 +282,7 @@ type Await union { An Instruction is the smallest unit of work that can be requested from a UCAN. It describes one `(resource, operation, input)` triple. The `input` field is free form, and depend on the specific resource and ability being interacted with, and is not described in this specification. -Using the JavaScript analogy from the introduction, an Instructon is similar to wrapping a call in a closure: +Using the JavaScript analogy from the introduction, an Instruction is similar to wrapping a call in a closure: ```json { @@ -533,7 +533,7 @@ The `Task` containing the `Instruction` and any configuration. ### 5.2.2 Authorization -The `auth` field MUST contain a [varsig] signing over an array of CIDs that includes the `Task`'s CID, signed by the issuer of the proofs. +The `auth` field MUST contain a [Varsig] signing over an array of CIDs that includes the `Task`'s CID, signed by the issuer of the proofs. ## 5.3 Invocation Tag @@ -549,18 +549,6 @@ type InvocationTag union { ### 5.4.1 Single Invocation - - - - - -// FIXME - - - - - - ```json { "_": { From 673065aee1edf9947da5ef9a06e65eb3a6d50c6f Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 6 Apr 2023 11:41:35 -0700 Subject: [PATCH 29/32] Starting a consistency pass --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index dbdc7b0d..9812c909 100644 --- a/README.md +++ b/README.md @@ -518,7 +518,7 @@ The `prf` field MUST contain links to any UCANs that provide the authority to pe ## 5.2 (Signed) Invocation -An `Invocation` is a signed `Context`. +An [Invocation] is a signed [Task]. ```ipldsch type Invocation struct { @@ -529,15 +529,15 @@ type Invocation struct { ### 5.2.1 Task -The `Task` containing the `Instruction` and any configuration. +The [Task] containing the [Instruction] and any configuration. ### 5.2.2 Authorization -The `auth` field MUST contain a [Varsig] signing over an array of CIDs that includes the `Task`'s CID, signed by the issuer of the proofs. +The `auth` field MUST contain a [Varsig] signing over an array of CIDs that includes the [Task]'s CID, signed by the issuer of the proofs. ## 5.3 Invocation Tag -An invocation capsule associates the `Invocation` with a versioned schema. This field is NOT REQUIRED. Wrapping an `Invocation` in an `InvocationTag` is RECOMMENDED in contexts where the schema and version are not clear from context, such as when it is being stores or passed around without being nested in another structure that defines the version in its schema. +An invocation capsule associates the [Invocation] with a versioned schema. This field is NOT REQUIRED. Wrapping an [Invocation] in an Invocation Tag is RECOMMENDED in contexts where the schema and version are not clear from context, such as when it is being stores or passed around without being nested in another structure that defines the version in its schema. ```ipldsch type InvocationTag union { @@ -687,7 +687,7 @@ type InvocationTag union { # 6 Result -A `Result` records the output of the [Task], as well as its success or failure state. +A Result records the output of the [Task], as well as its success or failure state. ## 6.1 Schema From 4f677807f9a8aba3a45487168cb348e95cdf4de0 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 6 Apr 2023 17:28:32 -0700 Subject: [PATCH 30/32] Fix link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9812c909..a7c6d59f 100644 --- a/README.md +++ b/README.md @@ -1487,7 +1487,7 @@ Thanks to [Rod Vagg](https://github.com/rvagg/) for the clarifications on IPLD S [Executor]: #212-executor [Haskell]: https://en.wikipedia.org/wiki/Haskell [Instruction]: #3-instruction -[Invocation]: #5-invocation +[Invocation]: #52-signed-invocation [Invoker]: #211-invoker [Pipeline]: #9-pipelines [Receipt]: #8-receipt From 5390ffbd71126ef9f0afbb12b262bdcba80b8687 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 6 Apr 2023 17:31:07 -0700 Subject: [PATCH 31/32] Fix markdown --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a7c6d59f..08491664 100644 --- a/README.md +++ b/README.md @@ -309,7 +309,7 @@ Using the JavaScript analogy from the introduction, an Instruction is similar to }) ``` -Later, when we explore promise [pipelines], this also includes capturing the promise, also with a natural analogy to closures: +Later, when we explore promise [pipelines][Pipeline], this also includes capturing the promise, also with a natural analogy to closures: ```json { @@ -727,7 +727,7 @@ If no information is available, this field SHOULD be set to `{}`. The result of an [Invocation] MAY include a request for further actions to be performed via "effects". This enables several things: a clean separation of pure return values from requesting impure tasks to be performed by the runtime, and gives the runtime the control to decide how (or if!) more work should be performed. -Effects describe requests for future work to be performed. All [Invocation]s in an [Effect] block MUST be treated as concurrent, unless explicit data dependencies between them exist via promise [Pipelines]. The `fx` block contains two fields: `fork` and `join`. +Effects describe requests for future work to be performed. All [Invocation]s in an [Effect] block MUST be treated as concurrent, unless explicit data dependencies between them exist via promise [Pipeline]s. The `fx` block contains two fields: `fork` and `join`. [Task]s listed in the `fork` field are first-class and only ordered by promises; they otherwise SHOULD be considered independent and equal. As such, atomic guarantees such as failure of one effect implying failure of other effects if left undefined. From d741eb54f8508d90062178a1bcf5e060970287ad Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Thu, 6 Apr 2023 17:32:26 -0700 Subject: [PATCH 32/32] TYpo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 08491664..b7daa7fb 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ By distinguishing invocation from delegation, agents are able to understand the Information about the scheduling, order, and pipelining of tasks is orthogonal to the flow of authority. An agent collaborating with the original executor does not need to know that their call is 3 invocations deep; they only need to know that they been asked to perform some task by the latest invoker. -As we shall see in the [discussion of promise pipelining][pipelines], asking an agent to perform a sequence of tasks before you know the exact parameters requires delegating capabilities for all possible steps in the pipeline. Pulling pipelining detail out of the core UCAN spec serves two functions: it keeps the UCAN spec focused on the flow of authority, and makes salient the level of de facto authority that the executor has (since they can claim any value as having returned for any step). +As we shall see in the [discussion of promise pipelining][Pipeline], asking an agent to perform a sequence of tasks before you know the exact parameters requires delegating capabilities for all possible steps in the pipeline. Pulling pipelining detail out of the core UCAN spec serves two functions: it keeps the UCAN spec focused on the flow of authority, and makes salient the level of de facto authority that the executor has (since they can claim any value as having returned for any step). ```txt ────────────────────────────────────────────Time──────────────────────────────────────────────────────►