Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

v1.0.0-rc.1 #2

Open
wants to merge 95 commits into
base: main
Choose a base branch
from
Open

v1.0.0-rc.1 #2

wants to merge 95 commits into from

Conversation

expede
Copy link
Member

@expede expede commented Oct 14, 2023

I may get pilloried for this version. WIP, obviously

Preview 📚

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:

  • While Embedded IPLD hasn't merged yet, we know exactly how it works
    • Mostly quibbling about format right now, but I hope to close it soon
    • This makes IPLD it WAY friendlier for those not deeply familiar with IPLD
  • Batch signatures needed some upgrading
    • Noteworthy that W3C folks are working on this, but no major JWT implementation has this yet
  • We understand now Invocations can take over some of the heavy lifting that Delegations were doing previously

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

  • Bump version to 1.0.0-rc.1

Structure

  • Remove revocation section
  • Point at ucan-wg/revocation
  • Point at ucan-wg/invocation
  • Remove ucan/* (moving to ucan-wg/ucan-uri)
  • Point at ucan-wg/ucan-uri
  • Move prf field to ucan-wg/invocation + add to top-level ucan-wg/spec
  • Use DNF + compat form

Time

  • Restrict time bounds to 53-bits (because JS)
  • Explicit time bounds checking logic
  • Make exp nullable

Prose

  • Remove signer role (confusing to some people)
  • Remove confusing analogy about lanyards in section 1.2
  • Change term "discharge" to something clearer
  • Clarify outer/inner terminology (or better: change it)
  • Clarify in section 6 [now] 5, that you only invalidate single capabilities; not everything
  • Remove old session ID recommendation now that we have content addressing
  • Move FAQ to the high level spec
  • Rename "top" to "wildcard" because it's a more familiar term for normies
  • Remove bottom case entirely in new syntax

Copy link

@Gozala Gozala left a 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

  1. 💚 Making UCAN contain single capability makes things so much easier both to explain and implement.
  2. 💚 Locking resource to a DID principal had been on my 🎄wish list.
  3. 💚 Removing proofs from delegations enables so many use cases that had not been possible prior.
  4. 💔 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)
  5. 💔 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 |
Copy link

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 ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep

README.md Outdated Show resolved Hide resolved
README.md Outdated

## 3.1 Version

The `udv` field sets the version of the UCAN Delegation specification used in the payload.
Copy link

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.

Copy link

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?

Copy link

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 } }

Copy link
Member

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] |
Copy link

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.

Copy link

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.

Copy link
Member Author

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

Copy link
Member Author

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?

Copy link

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.

Comment on lines +91 to +98
```json
"aud": "did:plc:ewvi7nxzyoun6zhxrhs64oiz",
"iss": "did:web:example.com",
```

```json
"aud": "did:pkh:eth:0xb9c5714089478a327f09197987f16f9e5d936e8a",
"iss": "did:plc:ewvi7nxzyoun6zhxrhs64oiz",
Copy link

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.

Copy link
Member Author

Choose a reason for hiding this comment

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

How so?

Copy link

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 Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
Comment on lines +20 to +28
type Signature union {
| batch BatchSig
| inline Bytes
} representation kinded

type BatchSig struct {
scp &[Any]
sig Bytes
}
Copy link

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.

Copy link
Member Author

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

Copy link

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.

Copy link
Member Author

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.

Comment on lines 1 to 4
type Delegation struct {
dgn &DelegationPayload
sig &Signature
}
Copy link

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:

  1. Use struct that embraces inline blocks and avoid all the problems above.
  2. 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.

Copy link

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:

Suggested change
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 payload, or whatever acronym makes sense so it could be use universally. Alternatively tuple representation could be used to remove need for naming those fields.

Copy link
Member Author

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 👍

}

type DelegationPayload struct {
udv Semver
Copy link

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.

Copy link
Member Author

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 🤔

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
expede and others added 8 commits October 31, 2023 15:24
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].
Copy link

@gobengo gobengo Dec 12, 2023

Choose a reason for hiding this comment

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

JARGON ALERT

Suggested change
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.

  1. 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 a capabilityDelegation verificationMethod. verificationMethod is basically DID documents abstraction over a cryptographic key.
  2. 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
  3. 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

Copy link

@bumblefudge bumblefudge Dec 20, 2023

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!)

Copy link

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

Copy link

@bumblefudge bumblefudge Feb 7, 2024

Choose a reason for hiding this comment

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

image
very few of the registered DID methods implement this optional property at all, tho? IMHO everything that the DID method spec defines as optional is "rely on or assume support for at your own risk"...

README.md Outdated Show resolved Hide resolved
@expede expede marked this pull request as ready for review December 20, 2023 16:12
}
```

| Field | Type | Required | Description |

Choose a reason for hiding this comment

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

Suggested change
| Field | Type | Required | Description |
| Field | JWT Property | Type | Required | Description |

Copy link

@gobengo gobengo Dec 20, 2023

Choose a reason for hiding this comment

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

Suggested change
| Field | Type | Required | Description |
| Field | Property | Type | Required | Description |

Copy link

@Gozala Gozala left a 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

  1. VarsigHeader is mentioned in fields but there are no details anywhere in here explaining what should it contain.
  2. 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).
  3. I would prefer loosing args as it would make exploring cond structure I've advocated for in user space without another set of constraints to worry about. For what it's worth args is actually how we used nb in web3.storage and per that experience I wish we have instead gone with cond 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] |
Copy link

Choose a reason for hiding this comment

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

Suggested change
| `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 |
Copy link

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 conds 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 |
Copy link

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.
Copy link

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:

  1. Check that payload is indeed signed with specified did:key.
  2. Verify that signing did:key is still in the did: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.

Comment on lines +91 to +98
```json
"aud": "did:plc:ewvi7nxzyoun6zhxrhs64oiz",
"iss": "did:web:example.com",
```

```json
"aud": "did:pkh:eth:0xb9c5714089478a327f09197987f16f9e5d936e8a",
"iss": "did:plc:ewvi7nxzyoun6zhxrhs64oiz",
Copy link

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",
Copy link

Choose a reason for hiding this comment

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

Suggested change
"subject": "Coffee",
"title": "Coffee",


The intended logic is expressible with [Conditions].

## Conditions
Copy link

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 `{}`.
Copy link

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.
Copy link

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 |
Copy link

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": {
Copy link

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)
Copy link

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 ─┐
Copy link

Choose a reason for hiding this comment

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

Suggested change
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}`:
Copy link

Choose a reason for hiding this comment

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

Suggested change
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}`:

@Gozala
Copy link

Gozala commented Feb 7, 2024

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 { with: "ucan:*", can: "*" }. I am realizing that this draft does not handle this case or at least is not specified in the text.

@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 ucan:*, but nothing is even worse.

Perhaps we could do something similar to what we did with exp: null to imply never expiring delegation and have sub: null to mean everything I could possibly delegate ?

Part of me also wishes I could constraint those in cond along with other things.

As an alternative I'd be in favor of making sub a SQLite like glob pattern (where * means any number on any chars and ? means any single character) as can fields are kind of already like it. That way we'd be able to delegate everything as { sub: "*", can: "*" }. I suppose only supporting * in addition to DIDs may be more pragmatic approach similar to sub: null and allow to be extended in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants