-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
v1.0.0-rc.1 #2
base: main
Are you sure you want to change the base?
v1.0.0-rc.1 #2
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like lot of changes here, but not all of them. Here is general breakdown
- 💚 Making UCAN contain single capability makes things so much easier both to explain and implement.
- 💚 Locking resource to a DID principal had been on my 🎄wish list.
- 💚 Removing proofs from delegations enables so many use cases that had not been possible prior.
- 💔 Not convinced by caveats array, lot of complexity for a very little benefit IMO. I would much rather introduce set of operators that could be used instead (more on that later)
- 💔 Requiring links is unfortunate and complicates things for JS and I would much rather avoid if we can.
README.md
Outdated
| Field | Type | Required | Description | | ||
|---------|-------------|----------|----------------------------------------------| | ||
| `ucd` | `&Payload` | Yes | The CID of the [Delegation Payload][Payload] | | ||
| `sig` | `Signature` | Yes | The `iss`'s [Signature] over the `ucd` field | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it signs over CID in binary format ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep
README.md
Outdated
|
||
## 3.1 Version | ||
|
||
The `udv` field sets the version of the UCAN Delegation specification used in the payload. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really wish we have adopted capsule types instead of fields with versions, it's a lot easier to write systems that work across versions that way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think i know what you mean, but can you give a quick example to illustrate what you'd like?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think i know what you mean, but can you give a quick example to illustrate what you'd like?
I was referring to what IPLD Schema calls keyed unions which later got named "capsule types". What we have in this spec is:
{
udv: "1.0.0",
...ucan
}
If your code can take ☝️ or some other type it becomes hard to guess which one you get. What I was suggesting instead is following:
{ "ucan@1.0.0": ucan }
Now you it's is clear that it is UCAN of specific version, better yet you can extend that type into a union with more versions you need to support and maybe even other things like invocations, revocations etc...
Downside is languages like TS or Rust aren't really fond of that pattern and you always have to wrap, while in previous pattern if you are aware what is it from context you don't have to wrap, but if you don't you could do something like { ucan: { udv: "1.0.0", ...ucan } }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rust is actually pretty happy with capsule types. We've switched to them in WNFS/rs-wnfs, and it's made some things easier.
However, putting a semantic version inside the key would be somewhat harder to deal with, since then you'd like to match on "ucan@1.0.x" or "ucan@1.x.x" in some cases. Putting the version inside is what we do in WNFS, but again that becomes less neat when you want have different fields for different versions. You could put the major version into the key, and the rest into the record, but that get's very unconventional fast: { "ucan@v1": { "subversion": "0.0", ... } }
.
README.md
Outdated
|
||
| Field | Type | Required | Description | | ||
|---------|-------------|----------|----------------------------------------------| | ||
| `ucd` | `&Payload` | Yes | The CID of the [Delegation Payload][Payload] | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is worth calling out that it is a lot more difficult in current (JS) IPLD stack to support things that span across blocks as we only have block encoders and decoders. I do personally like it but it is going to be an adoption burden.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it may be best to enforce inline blocks here per other spec to avoid the complications and later lift that limitation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if we need to enforce it, but I expect to use inline IPLD a lot
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you say more about why this is a problem in js-ipld? That seems like a pretty serious limitation in such a library. Isn't the block limit in IPFS (not IPLD) something like 2MB?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes recommended limit is around 2MB.
Can you say more about why this is a problem in js-ipld?
Before I go into JS specifics here I think fundamental language agnostic issue is what if I don't have a linked block ? When it's inline field that issue simply does not exist.
As of JS specifically, everything is built around js-multiformats library which has notion of the block and codecs that can encode / decode blocks. There is no notion of codecs that span multiple blocks nor generic structure for traversing objects that span multiple blocks. There had been several attempts to address this but nothing sticked and I think that is because it introduces asynchrony which in JS is far more consequential and invasive than other languages.
In go stack I think folks have embraced IPLD Prime which takes care of block loading behind the scenes and they can also block execution if needed so it's less of the issue there.
In Rust async also not as big of deal you can always block and wait, so I think loading blocks seems fine there, although having Result
is probably not great there either.
```json | ||
"aud": "did:plc:ewvi7nxzyoun6zhxrhs64oiz", | ||
"iss": "did:web:example.com", | ||
``` | ||
|
||
```json | ||
"aud": "did:pkh:eth:0xb9c5714089478a327f09197987f16f9e5d936e8a", | ||
"iss": "did:plc:ewvi7nxzyoun6zhxrhs64oiz", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These examples seem to contradict what spec says in regards to been specific with which key was used for signing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How so?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They don't have did fragment even though spec above says
the key used to sign the UCAN MUST be made explicit, using the [DID fragment] (the hash index) in the
iss
field
That said sounds like we're in agreement to dropping DID fragment and if so we don't need to change things here.
type Signature union { | ||
| batch BatchSig | ||
| inline Bytes | ||
} representation kinded | ||
|
||
type BatchSig struct { | ||
scp &[Any] | ||
sig Bytes | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would personally prefer use of BatchSig
and stick single CID when you're signing over just one payload. I'm not going to die on this hill, but seems like it would simplify implementations as there will be a single code path to consider. We could always cut down bytes in the next version if that proves necessary.
As an aside I also liked using term "Authorization" in ucan invocation spec as opposed to "signature" as I find later to be misleading.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah agreed. I had thought of that, but if we want to let people create JWTs (as a "signature type"), I think we will need a single signature. It adds some complexity, but it's more flexible to have both "bare" and "batch" (array) signatures.
I need to get to that spec shortly and explore more, though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I worry about subtle incompatibilities here, specifically sounds like if you used BatchSig
you won't be able to serialize it as JWT.
I would really like if we kept UCANs serialization agnostic (which current version in main branch is). That is to say if we support JWT format you should be able to serialize / deserialize any spec compliant UCAN as JWT. Or we can choose not to support JWT format. State where only subset of UCANs can be serialized would just be interop nightmare.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
specifically sounds like if you used BatchSig you won't be able to serialize it as JWT.
You should still be able to serializea single one as JWT. A single signature doens't need to be placed in a Merkle tree, and if it is, we can define it as a nonstandard signature type. You're right that this needs to be fully defined.
Our other option is to go back to a batch envelope (many resources per token), which has other tradeoffs.
delegation.ipldsch
Outdated
type Delegation struct { | ||
dgn &DelegationPayload | ||
sig &Signature | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As pointed out elsewhere I do worry that introducing links here makes things complicated in JS stack, specifically it makes JS dag-ucan impossible since JS IPLD stack has block codecs and no notion of dag codecs, which proved to be non-trivial task given that it introduces an async flows and the fact that only representation of set of blocks is a CAR. Even if we embraced CARs there is always possibility that it will contain subset of blocks raising questions whether you have to preload all the links or do that lazily (delaying errors).
I would very much prefer to either:
- Use struct that embraces inline blocks and avoid all the problems above.
- Make fields kinded unions that allow either links or inline blocks.
First option is more preferable as it removes block locality issues and addresses all of the other issues mentioned. Second option is workable as dag-ucan could only support inline blocks and let other libraries worry about supporting linked versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also argue that above type is pretty generic, and if we actually had generics in IPLD schema we would probably express it as follows:
type Delegation struct { | |
dgn &DelegationPayload | |
sig &Signature | |
} | |
type Authorization<Payload> struct { | |
pay &Payload | |
sig &Signature | |
} |
I would suggest renaming dng
field to something more generic like pay
load, or whatever acronym makes sense so it could be use universally. Alternatively tuple representation could be used to remove need for naming those fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest renaming dng field to something more generic like payload, or whatever acronym makes sense so it could be use universally.
💯 yeah I want to do this as part of the (batch) signature spec. This field is kind of pulling double duty as a not-quite-capsule and payload identifier.
Will fix 👍
delegation.ipldsch
Outdated
} | ||
|
||
type DelegationPayload struct { | ||
udv Semver |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer using capsule types instead as it makes structs self-describing and makes it possible to build versioned unions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm yeah. I kind of want to sign over this info, and that ends up being a lot of nesting, but not impossible I guess 🤔
Co-authored-by: Brian Ginsburg <7957636+bgins@users.noreply.github.com> Signed-off-by: Brooklyn Zelenka <be.zelenka@gmail.com>
Co-authored-by: Brian Ginsburg <7957636+bgins@users.noreply.github.com> Signed-off-by: Brooklyn Zelenka <be.zelenka@gmail.com>
Co-authored-by: Irakli Gozalishvili <contact@gozala.io> Signed-off-by: Brooklyn Zelenka <be.zelenka@gmail.com>
|
||
## 3.2 Principals | ||
|
||
The `iss` and `aud` fields describe the token's principals. They are distinguished by having DIDs. These can be conceptualized as the sender and receiver of a postal letter. The token MUST be signed with the private key associated with the DID in the `iss` field. Implementations MUST include the [`did:key`] method, and MAY be augmented with [additional DID methods][DID]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JARGON ALERT
The `iss` and `aud` fields describe the token's principals. They are distinguished by having DIDs. These can be conceptualized as the sender and receiver of a postal letter. The token MUST be signed with the private key associated with the DID in the `iss` field. Implementations MUST include the [`did:key`] method, and MAY be augmented with [additional DID methods][DID]. | |
The `iss` and `aud` fields describe the token's principals. They are distinguished by having DIDs. These can be conceptualized as the sender and receiver of a postal letter. The token MUST be signed with a | |
[verification method](https://www.w3.org/TR/did-core/#verification-methods) | |
with [verification relationship](https://www.w3.org/TR/did-core/#verification-relationships) | |
[`capabilityDelegation`](https://www.w3.org/TR/did-core/#capability-delegation) | |
in the [DID document](https://www.w3.org/TR/did-core/#dfn-did-documents) | |
[resolved](https://www.w3.org/TR/did-core/#resolution) | |
from the DID in the `iss` field of the UCAN. Implementations MUST include the [`did:key`] method, and MAY be augmented with [additional DID methods][DID]. |
this is an ancient did encantation that is probably a good idea 😅
jk. Sorry that's so dense, but it's a lot of jargon and I wanted to have hypertext be able to point people to what they'd need to know for it to be relatively self describing.
Here's what matters.
- It works with
did:key
and you don't have to worry about it if that's all your using. (iiuc)did:key
is defined in such a way to basically expand into a did document without using the network and the corresponding cyrptographic key deocded from the did:key is automatically added as acapabilityDelegation
verificationMethod.verificationMethod
is basically DID documents abstraction over a cryptographic key. - It allows for a lot more end-user control for did methods where the user authors their own did document
- my understanding is that in certain contexts it is a super strong best practice to use different signing keys for e.g. capability delegation vs invocation, and in general to separate keys by purpose and/or minimize key reuse
- it will be easier to interpret the spec for an implementor validating dids here because it is using precise language on the way an implementor needs to verify the UCAN sig against the result of DID resolution, which is a DID Document that may be more expressive than the simple case of
did:key
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe
from the DID in the
iss field of the UCAN. Implementations MUST include the [
did:key] method, and MAY be augmented with [additional DID methods][DID].
-->
from the DID in the
iss field of the UCAN. Implementations MUST include the [
did:key] method, and MAY be augmented with [additional DID methods][DID] that support the above flow.
(Not all DID methods support the key names capabilityDelegation
or arbitrary key names!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Not all DID methods support the key names capabilityDelegation or arbitrary key names!)
I think it's fine with text as is. did-core defines capability delegation so that's all i need to refer to without worrying about methods that implemented it (fully/partially/correctly/incorrectly). If in practice someone is using UCANs with a did method that doesn't support capability delegations.... well IMO I think that should basically be inherently impossible but doesn't require spec text qualifications to point it out. did using method that doesn't support capability verification methods is just like using a did method that does, but the did doc has an empty array of them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | ||
``` | ||
|
||
| Field | Type | Required | Description | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Field | Type | Required | Description | | |
| Field | JWT Property | Type | Required | Description | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Field | Type | Required | Description | | |
| Field | Property | Type | Required | Description | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Provided some feedback. I'm mostly happy with it but here is high level breakdown of my feedback
VarsigHeader
is mentioned in fields but there are no details anywhere in here explaining what should it contain.- I really think we could really use bit more structure for
cond
. It still remain very extensible, yet provide means to interop or at least know whether validator supports such conditions or not (provided bunch more details on that inline). - I would prefer loosing
args
as it would make exploringcond
structure I've advocated for in user space without another set of constraints to worry about. For what it's worthargs
is actually how we usednb
in web3.storage and per that experience I wish we have instead gone withcond
route (specifically how I described them in inline)
| Field | Type | Required | Description | | ||
|---------------------|---------------------|----------|--------------------------| | ||
| `h` | `VarsigHeader` | Yes | The Varsig header | | ||
| `ucan/d/1.0.0-rc.1` | `InvocationPayload` | Yes | The [Invocation Payload] | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| `ucan/d/1.0.0-rc.1` | `InvocationPayload` | Yes | The [Invocation Payload] | | |
| `ucan/d/1.0.0-rc.1` | `DelegationPayload` | Yes | The [Delegation Payload] | |
Should this be delegation payload instead ?
| `aud` | `DID` | Yes | Audience DID (receiver) | | ||
| `sub` | `DID` | Yes | Principal that the chain is about (the [Subject]) | | ||
| `can` | `String` | Yes | The [Command] to eventually invoke | | ||
| `args` | `{String : Any}` | Yes | Any [Arguments] that MUST be present in the Invocation | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would personally prefer to leave it out and perhaps specify how same can be expressed in cond
s instead. I do not feel very strongly about it, it's just introduce more surface to cover.
For more context I have been thinking of Conditions
could use specific operators, that we could standardize over time. That would still leave space for extensibility allowing custom domain specific operators at the expense of less interop. Given this perspective I'd be inclined to just have standard operator for equality from the get go.
| `can` | `String` | Yes | The [Command] to eventually invoke | | ||
| `args` | `{String : Any}` | Yes | Any [Arguments] that MUST be present in the Invocation | | ||
| `nonce` | `Bytes` | Yes | Nonce | | ||
| `cond` | `[Condition]` | Yes | Any additional [Condition]s | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: This is very subjective, but fields like where
or when
invite AND semantics to me while cond
invites OR semantics, hence I'd rather use one of the other two. I'd especially advocate for where
due to familiarity from various query DSLs.
|
||
The `iss` and `aud` fields MUST contain a single principal each. | ||
|
||
If an issuer's DID has multiple or mutable keys (e.g. [`did:plc`], [`did:web`]), the key used to sign the UCAN MUST be made explicit, using the [DID fragment] (the hash index) in the `iss` field. The `aud` field SHOULD NOT include a hash field, as this defeats the purpose of delegating to an identifier for multiple keys instead of an identity. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that was exactly my position. What did wanted is to capture both mutable identifier did:web:*
along with did:key:
that was used, specifically when issuer is did:web:
. That way I can:
- Check that payload is indeed signed with specified
did:key
. - Verify that signing
did:key
is still in thedid:web
document.
I'm afraid did fragment does really accomplish what I wanted since I can not do 1. without doing DID resolution. Furthermore it introduces more issues because fragment may point to different key even though signing key still may be in the document, introducing false positives.
```json | ||
"aud": "did:plc:ewvi7nxzyoun6zhxrhs64oiz", | ||
"iss": "did:web:example.com", | ||
``` | ||
|
||
```json | ||
"aud": "did:pkh:eth:0xb9c5714089478a327f09197987f16f9e5d936e8a", | ||
"iss": "did:plc:ewvi7nxzyoun6zhxrhs64oiz", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They don't have did fragment even though spec above says
the key used to sign the UCAN MUST be made explicit, using the [DID fragment] (the hash index) in the
iss
field
That said sounds like we're in agreement to dropping DID fragment and if so we don't need to change things here.
README.md
Outdated
"args": { | ||
"from": "alice@example.com", // Matches above | ||
"to": ["bob@example.com", "carol@elsewhere.example.com"], | ||
"subject": "Coffee", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"subject": "Coffee", | |
"title": "Coffee", |
|
||
The intended logic is expressible with [Conditions]. | ||
|
||
## Conditions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Providing bit more context to what I have mentioned in the section above. I would prefer if conditions had a bit more structure to them than their currently open form. Specifically I would very much prefer if conditions had requirement for "Operator", that way we could gradually introduce standard operators yet leave room for domain specific ones allowing implementations to interop on standard operators and opt-out of interop by introducing custom operators. At the same time this could establish path for standardizing established operators over time.
More concretely I would propose expressing conditions as triples of [operator, operand, modifier]
, if were to do that we could get rid of args
and instead express delegation from the above as follows:
{
"can": "msg/send",
"cond": [
["=", "from", "alice@example.com"],
["=", "to", ["bob@example.com"]],
]
}
I realize this could lead into discussion what kind of "operands" are supported as in what if I want to reach nested fields instead etc... But I think we can start simple and pun on that. Specifically we could only specify =
operator that only take strings and anything in the modifier and impose semantics currently defined for args
. Operands that contain "." or "/" characters can be reserved for future revisions.
P.S. It may make senes to debate actual format, but I'd argue that even specifying that there is notion of operator
, operand
and modifier
/ constraint
would be a lot better than keeping it completely open to interpretation.
P.P.S. I can also be convinced that [operator, operand]
might be a better alternative.
|
||
### The True Condition | ||
|
||
The "true condition" MUST (vacuously) represent the lack of Conditions: it is equivalent to `true` in predicate terms. It SHOULD be expressed simply by not including a Condition, but MAY be expressed as `{}`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One other thing that had been on my mind is to (exploit product types) use objects to imply AND
semantics, and use arrays for OR
semantics. That way true condition is naturally going to be {}
and false
condition will be []
.
Obvious question however is what the keys of conditions should be, probably does not matter and we could recommend starting with 0 and incrementing by one.
I'm sure negation will be something we'd want next but thought I'd throw this in her eanyway.
|
||
### Recipient Validation | ||
|
||
An agent executing a capability MUST verify that the outermost `aud` field _matches its own DID._ The associated ability MUST NOT be performed if they do not match. Recipient validation is REQUIRED to prevent the misuse of UCANs in an unintended context. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this belong in the delegation spec ? Perhaps it should be moved to invocation one instead ? Or maybe it should be reframed so it's not about the execution but rather about received delegation ?
|
||
| Field | Type | Required | Description | | ||
|---------------------|---------------------|----------|--------------------------| | ||
| `h` | `VarsigHeader` | Yes | The Varsig header | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still not sure what goes here, I don't think it was covered anywhere in the spec
"s": {"/": {"bytes": "7aEDQLYvb3lygk9yvAbk0OZD0q+iF9c3+wpZC4YlFThkiNShcVriobPFr/wl3akjM18VvIv/Zw2LtA4uUmB5m8PWEAU"}} | ||
"p": { | ||
"h": {"/": {"bytes": "NBIFEgEAcQ"}}, | ||
"ucan/d/1.0.0-rc.1": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is aud
missing in the Delegation payload example?
|
||
The `cond` field MUST contain any additional conditions. This concept is sometimes called a "caveat". Conditions constrain the capability in two ways: | ||
|
||
- Syntactic constraints on [Arguments] (length, regex, inclusion) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading the preview, and it looks like [Arguments]
may need a link definition.
``` js | ||
[ | ||
{ // ┐ | ||
a: 1, // ├─ Confition ─┐ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a: 1, // ├─ Confition ─┐ | |
a: 1, // ├─ Condition ─┐ |
|
||
The above Delegation MUST be interpreted as "may send email from `alice@example.com` on Mondays as long as `bob@exmaple.com` is among the recipients" | ||
|
||
The `if` field MUST take the following shape: `[{}]`. The array represents a logical `all` (chained `AND`s). To represent logical `OR`, issue another delegation with that attenuation. For instance, the following represents `{a: 1, b:2} AND {c: 3} AND {d: 4}`: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The `if` field MUST take the following shape: `[{}]`. The array represents a logical `all` (chained `AND`s). To represent logical `OR`, issue another delegation with that attenuation. For instance, the following represents `{a: 1, b:2} AND {c: 3} AND {d: 4}`: | |
The `if` field MUST take the following shape: `[{}]`. The array represents a logical `all` (chained `AND`s). To represent logical `OR`, issue another delegation with that attenuation. For instance, the following represents `{a: 1, b: 2} AND {c: 3} AND {d: 4}`: |
I have recently been dealing with a case where account re-delegates anything ever delegated to it to some agent. In previous ucan spec this could be expressed as @expede what is the current take on this ? We really would like to support this somehow to handle an account recovery. I am not a big fan of Perhaps we could do something similar to what we did with Part of me also wishes I could constraint those in As an alternative I'd be in favor of making |
I may get pilloried for this version. WIP, obviouslyPreview 📚
Okay, this version switches to IPLD. This makes it much easier to not need a IPLD version off to the side, and many teams that have adopted UCAN already use IPLD somewhere in their stack. There is a contingent of people that feel strongly in favour of JWT for a variety of reasons. I also defended the JWT strategy for a long time, beacuse I had many first-hand converstaions of "I need to sell this to management, please tell me it's a JWT and not some inscrutable binary format".
A few things have changed:
I believe that this proposal makes writing both UCAN Delegations and libraries much easier and more comprehensible. It also lowers our maintenance burden between multiple formats.
Changelog
Metadata
1.0.0-rc.1
Structure
ucan-wg/revocation
ucan-wg/invocation
ucan/*
(moving toucan-wg/ucan-uri
)ucan-wg/ucan-uri
prf
field toucan-wg/invocation
+ add to top-levelucan-wg/spec
Time
exp
nullableProse
6[now] 5, that you only invalidate single capabilities; not everything