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

UCAN v0.9.0 #55

Merged
merged 83 commits into from
Sep 2, 2022
Merged

UCAN v0.9.0 #55

merged 83 commits into from
Sep 2, 2022

Conversation

expede
Copy link
Member

@expede expede commented Apr 6, 2022

Change Log 🪙🪵

Added 📥

Removed 📤

  • Remove IPFS/DHT requirement
  • Remove URI selection by scheme (e.g. no more "with": "dns:*")
    • This was actually very bad and broke the URI contract

Move Out of Core Spec 🪁

  • [x] Consider extending my: to all parenthood cases, even specific values (CC @matheus23)
  • Transport agnostic point-to-point protocol
  • HTTP cache header protocol <- HTTP stuff should live in own spec
  • Resource selection (e.g. "with": "ucan:uri:dns")

Resolves 🛠️

@cla-bot cla-bot bot added the cla-signed label Apr 6, 2022
@expede
Copy link
Member Author

expede commented Apr 7, 2022

cc @dholms FYI this is going to include removal of the DHT dependency, and replace it with a point-to-point (e.g. HTTP) protocol. If you have any thoughts on this direction, this is the time! 😉

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
@expede expede self-assigned this Apr 8, 2022
@expede expede force-pushed the 0.9 branch 2 times, most recently from 0cb321f to f784f03 Compare April 12, 2022 06:52
@expede
Copy link
Member Author

expede commented Apr 18, 2022

Added this line to the 0.9 roadmap:

Consider extending my: to all parenthood cases, even specific values (CC @matheus23)

#21 (comment)

@ukstv
Copy link

ukstv commented Apr 23, 2022

Hey, I might be missing something here, but as far as I understand, UCAN thing is not really a valid JWT, even in this form. You mention mandatory support of did:key. Apparently, it allows using some exotic signature suites like BLS, which can not be really supported in older JWT libraries, as it does not belong to JOSE algorithms (AFAIK!). Do you apply some constraints on the list of available algorithms, like using only ed25519 and RSA did:key, or is the whole backwards compatibility story a bit of a misnomer?

If my basic understanding is correct, then UCAN supports did methods that use JOSE algorithms exclusively. How can it be both compatible with existing JWT tooling and support advanced did methods?

@expede
Copy link
Member Author

expede commented Apr 23, 2022

@ukstv Technically DID can support any signature scheme, yup! Today we support EdDSA, ECDSA, and RSA only, which are all in JWT. IIRC EdDSA is in a separate JOSE extension IETF spec, but is extremely widely supported in libraries (it's de facto supported).

We should absolutely be explicit about this in the spec. We also don't allow HMAC verification.

A library supporting more methods "off spec" is possible today (we've done proof of concepts with ION, for example), but can't expect that to be compatible with "any" other implementation. The spec if just here to be the line of "what is interoperable".

If there's a good case made, we're open to effectively forking JWT (at which point, we drop the weird multi-section formatting with .s and stuff, trim a few bytes from redundant fields, etc). Using JWT as-is has a few arguments:

  1. Easy to build new implementations out of existing components
  2. Extensive tooling (though not for the UCAN parts — we've started on some at ucan.xyz)
  3. Familiarity for web devs / "sell to management"

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
| `att` | `Json[]` | Attenuations | Yes |

### 3.2.1 Principals

The `iss` and `aud` fields describe the token's principals. 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](https://w3c-ccg.github.io/did-method-key/), and MAY be augmented with [additional DID methods](https://www.w3.org/TR/did-core/).

The underlying key types RSA, ECDSA, and EdDSA MUST be supported. Use of ECDSA is supported but [RECOMMENDED that another key type be preferred](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Security).
Copy link
Member Author

Choose a reason for hiding this comment

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

Would that not be covered by the alg field in the JWT header?

@expede expede marked this pull request as ready for review May 26, 2022 01:26
@expede expede requested a review from matheus23 as a code owner May 26, 2022 01:26
@expede
Copy link
Member Author

expede commented May 26, 2022

I flipped this to Ready for Review. I think that we're mainly on the same page about the scope of 0.9 from the conversation above, but please do mention anything that should or should not be in here. I think the most controversial things will be:

  1. Requiring my: for introduction by parenthood
  2. The label nb for extensible fields

Open to folks flagging typos or nitpicks. VERY open to approvals 😜

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
A UCAN token MUST be referenced as [CIDv1](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) with the following configuration:
* CID Version: `1`
* Multibase: [`b` base32](https://github.com/multiformats/multibase/blob/master/multibase.csv#L12)
* Multicodec: [`0x55` raw data](https://github.com/multiformats/multicodec/blob/master/table.csv#L39)
Copy link
Member

Choose a reason for hiding this comment

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

Would this explicitly deny using dag-ucan in valid UCANs?

Copy link
Member Author

@expede expede May 31, 2022

Choose a reason for hiding this comment

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

That's a really good point!

@Gozala: you're proposing the use of dag-json for the deterministic codec, yes? IIRC dag-ucan didn't go forward.

Copy link
Contributor

Choose a reason for hiding this comment

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

Would this explicitly deny using dag-ucan in valid UCANs?

It does sound like it would indeed make dag-ucan incompatible with a spec as it uses CBOR encoding with a following schema #67, when possible.

@expede is this intentional ? Otherwise can we either include CBOR variant or at least change wording so that RAW isn't the only valid option.

Copy link
Contributor

Choose a reason for hiding this comment

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

@Gozala: you're proposing the use of dag-json for the deterministic codec, yes? IIRC dag-ucan didn't go forward.

I'm not sure I fully understand that question, I think there are couple of things mixed up, so I"ll try to clarify:

  1. dag-ucan did go forward and it uses CBOR encoding when possible (that is turning that CBOR to JSON and then formatting as JWT produces same signature), and RAW encoding otherwise.
  2. Idea of introducing dag-ucan multicodec code was dropped in favor of just CBOR because:
    1. It did not provide a lot of benefit, mostly signaling in links
    2. And came with tradeoff that required registering new codecs even though it is CBOR with some schema.
  3. I have been advocating for ucan implementations using dag-json as that would allow them to be representation agnostic (could be encoded in CBOR without signature changes). However that is unrelated to dag-ucan.

Copy link
Member Author

Choose a reason for hiding this comment

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

@Gozala There was a previous version that included the dag-ucan multicodec. When that PR was nixed, I dropped its prefix from this document. I just forgot to update this section after dag-json was settled on. I'll add that now 👍

Copy link
Member Author

Choose a reason for hiding this comment

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

@Gozala any concern with limiting it to CIDv1 + base32?

Copy link
Member

@matheus23 matheus23 left a comment

Choose a reason for hiding this comment

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

Only a couple of typos I noticed + a question about allowing a dag-ucan/other codecs in CIDs, but that question is mostly out of interest.
So apart from fixing typos, let's :shipit: :)

Copy link

@olizilla olizilla left a comment

Choose a reason for hiding this comment

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

Some fixes for broken internal links after the great renumbering

I found a couple the old fashioned way when clicking around the rendered version, and used:

$$('a[href^="#"]').filter(el => !document.getElementById(`user-content-${el.getAttribute('href').substring(1)}`)).map(el => el.innerText)

to find the rest. Provided here in case it's handy for future re-numberings. 🔢🔍✨

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
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
Copy link
Member

@hugomrdias hugomrdias left a comment

Choose a reason for hiding this comment

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

left some suggestions to fix typos.

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
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated
A UCAN token MUST be referenced as [CIDv1](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) with the following configuration:
* CID Version: `1`
* Multibase: [`b` base32](https://github.com/multiformats/multibase/blob/master/multibase.csv#L12)
* Multicodec: [`0x55` raw data](https://github.com/multiformats/multicodec/blob/master/table.csv#L39)
Copy link
Contributor

Choose a reason for hiding this comment

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

Would this explicitly deny using dag-ucan in valid UCANs?

It does sound like it would indeed make dag-ucan incompatible with a spec as it uses CBOR encoding with a following schema #67, when possible.

@expede is this intentional ? Otherwise can we either include CBOR variant or at least change wording so that RAW isn't the only valid option.

README.md Outdated
A UCAN token MUST be referenced as [CIDv1](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) with the following configuration:
* CID Version: `1`
* Multibase: [`b` base32](https://github.com/multiformats/multibase/blob/master/multibase.csv#L12)
* Multicodec: [`0x55` raw data](https://github.com/multiformats/multicodec/blob/master/table.csv#L39)
Copy link
Contributor

Choose a reason for hiding this comment

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

@Gozala: you're proposing the use of dag-json for the deterministic codec, yes? IIRC dag-ucan didn't go forward.

I'm not sure I fully understand that question, I think there are couple of things mixed up, so I"ll try to clarify:

  1. dag-ucan did go forward and it uses CBOR encoding when possible (that is turning that CBOR to JSON and then formatting as JWT produces same signature), and RAW encoding otherwise.
  2. Idea of introducing dag-ucan multicodec code was dropped in favor of just CBOR because:
    1. It did not provide a lot of benefit, mostly signaling in links
    2. And came with tradeoff that required registering new codecs even though it is CBOR with some schema.
  3. I have been advocating for ucan implementations using dag-json as that would allow them to be representation agnostic (could be encoded in CBOR without signature changes). However that is unrelated to dag-ucan.

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

_UCAN does not have any special protection against person-in-the-middle (PITM) attacks._

Were a PITM attack successfully performed on a UCAN delegation, the proof chain would contain the attacker's DID(s). It is possible to detect this scenario and revoke the relevant UCAN but does require special inspection of the topmost `iss` field to check if it is the expected DID. Therefore, it is strongly RECOMMENDED to only delegate UCANs to agents that are both trusted and authenticated and over secure channels.

## 12.4 Why are the superuser and delegation abilities separate?
Copy link
Contributor

@Gozala Gozala Aug 8, 2022

Choose a reason for hiding this comment

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

Am I correct in interpreting this as * means all abilities including ones that may be introduced in the future. While ucan/delegate means all abilities that are present in proofs ? If so I think I'm starting to get the distinction, yet I think that could be made more clear.

In other words following capability

{ 
    "with": "owned://did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV/wnfs", 
    "can": "*" 
  }

Implies that all wnfs:// capabilities of did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV had been delegated even though they aren't listed by did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV.

On the other hand following capability:

{ 
    "with": "ucan:*", 
    "can": "ucan/DELEGATE" 
  }

implies that all the of the capabilities from all proofs have been (re)delegated.

Confusing bit here is that two either never overlap (in which case I think there's no point in having ucan/delegate) or they do and following capability:

{ 
    "with": "owned://did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV/wnfs", 
    "can": "ucan/DELEGATE" 
  }

has different semantics from the 1st one (with same with and "can": "*") and implies to select only explicitly delegated "wnfs" capabilities from did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV as opposed to all the "wnfs" capabilities from that actor.

If later is true I think disambiguating between these delegations using different URI schemas seems a lot less confusing to me.

Copy link
Member Author

@expede expede Aug 9, 2022

Choose a reason for hiding this comment

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

In other words following capability
[...]
Implies that all wnfs:// capabilities of did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV had been delegated even though they aren't listed by did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV.
On the other hand following capability:
[...]
implies that all the of the capabilities from all proofs have been (re)delegated.

Yup, that's the distinction! ucan/delegate only makes sense in the context of ucan:, in the same way that msg/send does make sense for mailto: but not wnfs:.

I'll add some clarifying text to that effect 👍

implies that all the of the capabilities from all proofs have been (re)delegated.

Also {with: "ucan:Qm12345:", can: "ucan/delegate"} would delegate from that one UCAN. This is the any (i.e. "any" / whatever happens to be in Qm12345). It may be a lot of power, or very little.

On the other hand, can: "*", that would assert the maximum rights to the resource ("all rights"), which need to be be ownership, or backed up with exactly that from a proof.

Confusing bit here is that two either never overlap (in which case I think there's no point in having ucan/delegate)

Tell me about not having ucan/delegate then? msg/send also doesn't overlaps with CRUD actions, and often resources can use only one or the other.

Copy link
Contributor

Choose a reason for hiding this comment

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

Tell me about not having ucan/delegate then? msg/send also doesn't overlaps with CRUD actions, and often resources can use only one or the other.

There are few things that I think contribute to the confusion:

  1. The * is a special form (only thing that does not need to be namespaced). It is used also in with to match anything. However in case of can it's semantics change to mean maximum rights to the resource.
  2. It is confusing (and annoying) that * in can field can only be used with some protocol schemas and not the other. In turn it creates more opportunities to have invalid UCANs (I'm pretty sure we even have some of those in our system). It is true that not every can be used in conjunction with every with, but given a special form I'd expect it to.
  3. Just like you could use * in "with": "ucan:*" to match pattern I would expect to do the same in can: "store/*" to match all the capabilities that were delegated namespaces with store.

In summary it feels composable but it is not and it is not intuitively obvious which things can be used in conjunction and which can't. This adds to complexity which I fear can lead to implementation incompatibilities due to misinterpretation.

It seems more intuitive to capture whether resource refers to explicitly delegated or implicitly owned capabilities in "resource" selector than in ability. I could be convinced that it should be captured in "ability", but even than using any other identifier but * would be far less confusing.

Alternatively encoding "superuser ability" in a different special form might worth considering

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok so here is an example of the delegated capabilities

[
  { 
    "with": "owned://did:key:zAlice/wnfs", 
    "can": "*" 
  },
  {
     "with": "owned://did:key:zBob/wnfs",
     "can": "ucan/delegate"
  }
]

So here is what I find unclear about this:

  1. What happens if Alice delegated just specific wnfs capabilities as opposed to super user ability ? Is above redelegation invalid or is it just redelegates ones that Alice delegated ?
  2. What happens if Bob delegated "superuser ability" ? Does above UCAN redelegates all the wnfs abilities from Bob including future ones (which would mean it would be no different from using "can": "*") or does not delegate any wnfs ability from Bob ? Or perhaps it implies abilities that were known to "wnfs" at time the delegation occurred (I hope not this one) ?

Update: I am realizing now that can: "*" is reserved only for owned: schema, and "ucan/delegate" for "ucan" schema which would mean above UCAN would be invalid, still I think it illustrates some of the confusion.

Copy link
Member Author

Choose a reason for hiding this comment

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

@Gozala I just watched @hugomrdias's UCAN talk from Iceland (which I missed because I was giving a concurrent talk at the same time), and the way he's framing the foo/* capabilities makes a ton of sense. It's a slightly different way of looking at the problem, but I think it's better. I'll make that change 👍

@Gozala
Copy link
Contributor

Gozala commented Aug 9, 2022

@expede I have evaluated changes required to switch from "my:*" schema to "my" field in our implementation and I'm afraid I'm arriving to conclusion that this idea may have been a bad one. I feel bad for pushing for it without evaluating it first, but maybe it is not too late to reconsider ? Here are some of my the unstructured thoughts about it:

  • UCAN validator needs to recognize which capabilities can be issued by an actor to distinguish them from ones that are delegated.
    • ucanto validator provides canIssue(capability, issuer): boolean hook to make that configurable.
    • By default it is uses canIssue(cap, iss) => cap.with === iss, implying that only owner of the did can issue capabilities for that did.
    • ucanto does not recognized my:* as one that actor can issue, instead it has my(iss): cap[] hook which is used to expand my:* forms and then select matches from it.
  • In other domains decisions made by ucanto may not fit so there needs to be another signaling mechanism which used to be e.g my:wnfs://....
    • However it seems that validating that would still require out of bound checks that claimed resource is actually owned by user.
  • I think signaling whether capability is owned by iss or not should be left out of spec that way ucanto can use it's did matching logic while other implementations may embrace my: schema

@expede
Copy link
Member Author

expede commented Aug 11, 2022

@Gozala

but maybe it is not too late to reconsider ?

I've been waiting for your review exactly for this reason 👍

I think signaling whether capability is owned by iss or not should be left out of spec that way ucanto can use it's did matching logic while other implementations may embrace my: schema

I'd love to dig into this more, because I'm having a hard time piecing together how the validation and rooted authority would work in this version. A sync call may be the fastest way to iterate on some ideas, but let me know! I'll ping you on Discord.

Copy link
Member Author

@expede expede left a comment

Choose a reason for hiding this comment

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

cc @Gozala just some commentary on the changes after our call. Does this match your picture?

README.md Outdated
@@ -338,7 +337,7 @@ The underlying key types RSA, ECDSA, and EdDSA MUST be supported. Use of ECDSA i

The `nbf` field is OPTIONAL. When omitted, the token MUST be treated as valid beginning from the Unix epoch. Setting the `nbf` field to a time in the future MUST delay using a UCAN. For example, pre-provisioning access to conference materials ahead of time but not allowing access until the day it starts is achievable with judicious use of `nbf`.

The `exp` field MUST be set. If the time is in the past, the token MUST fail validation.
The `exp` field MUST be set. Following the [principle of least authority](https://en.wikipedia.org/wiki/Principle_of_least_privilege), it is RECOMMENDED to give a timestamp expiry for UCANs. If the token explitely never expires, the `exp` field MUST be set to `null`. If the time is in the past at validation time, the token MUST be treated as expired and invalid.
Copy link
Member Author

Choose a reason for hiding this comment

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

Added the option to use an explicit null to the expiry. The other option that we discussed was setting it to super far in the future (e.g. 9999999999), which is roughly what we do today even if it doesn't capture the intention.

We want this field to be fairly salient — no expiry is potentially dangerous and not listing it makes that easy to miss — hence not having it be optional.

README.md Outdated

This field being separate is very important. Without the distinction of introduction by parenthood, there exists ambiguity in the capability provenance could be exploited by a malicious user in an unrelated proof, forcing the validly delegated capability to appear as though it has an invalid ownership claim. Separating these capabilities into their own array makes the claimed source of authority explicit.

### 3.2.6 Attenuation
Copy link
Member Author

Choose a reason for hiding this comment

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

@matheus23 from the call with @Gozala earlier, it sounds like the ambiguity of "it may be in the chain or in the proofs and we have to handle either" is just less error prone and actually more ergonomic. I realize that this is comes full circle 😅 Please do push back if it's an "over my dead body"

Copy link
Contributor

Choose a reason for hiding this comment

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

For more context, in our uses we can tell if capability can be issued by an actor of it has to be delegated, specifically if it matches ${protocol}://${my_did}/* it can be self issued otherwise it needs to be delegated.

That is to say that how you resolve ambiguity may vary and that is also an argument for not prescribing it via spec.

Copy link
Member Author

@expede expede Aug 20, 2022

Choose a reason for hiding this comment

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

Ah I see. This is what the previous my/as and now the own scheme are for. You can't use a DID in an arbitrary URI as the host field, nor a * path to mean multiple resources of that type. It depends on the definition of the specific URI.

This proposal merely suggests reformatting that into a safer, more widely compatible form.

owned://did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV/*
owned://did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV/dns
own://did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV/*
own://did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV/dns
Copy link
Member Author

Choose a reason for hiding this comment

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

We could potentially pull this out into its own spec, as it's not a hard requirement for the core spec.

Copy link
Contributor

Choose a reason for hiding this comment

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

@expede This is kind of a thing that we probably would have expressed as follows instead

  1. Can do anything did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV could do
{ can: "*", with: "did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" }
  1. Can do same DNS stuff as did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV
{ can: "*", with: "dns://did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" }

If expressed as above own: becomes unnecessary, for the same reason as my is unnecessary - if issuer is same ID it can self issue, otherwise it must be delegated from the did.

Copy link
Member Author

@expede expede Aug 19, 2022

Choose a reason for hiding this comment

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

@Gozala I see what you're trying to do, but both break the URI schemes which are defined in their own specs. For example, dns://did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV would need to resolve did:key:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV as a DNS host as defined in RFC 4501 and RFC 3986.

The example you give above is not formatted as that, and so a DNS parser would fail ahead of a lookup. What own gives you here is a signal that we're not using the dns: URI scheme. The host authority for DNS is the source authority for resolution, not the owner of the DNS name (you may trust Google's resolver, for instance)

Hosts are also case insensitive in the URI spec, but DIDs are not:

host = IP-literal / IPv4address / reg-name
[...]
Although host is case-insensitive, producers and normalizers should use lowercase for registered names and hexadecimal addresses for the sake of uniformity, while only using uppercase letters for percent-encodings.

And the host is intended to resolve to a IP literal, which DIDs don't do.

If you want to use the user field, not all URIs support it, and the URI ABNF requires a host to be specified for the user (helpful railroad diagram here).

Most DID methods are also resources themselves, where you're maintaining PKs on a DID document. Saying { can: "*", with: "did:<foo>:zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" } for example would imply the ability to update the actual DID document, not the resources accessible or owned by that DID.

Copy link
Member Author

@expede expede Aug 19, 2022

Choose a reason for hiding this comment

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

FWIW, Fission has done variants of both of the above in the past, but I've come to realize that once we switched to URI resources, we should probably honour the URIs that we say they are, otherwise there's lots of sharp edges, potential for confusion, attack surface (URI parsing attacks are a thing), and difficulty in reusing existing URI tooling.

README.md Outdated
@@ -598,7 +587,6 @@ Revocations MAY be deleted once the UCAN that they reference expires or otherwis
│ │ │
│ iss: Alice │ │
│ aud: Bob │ ├─ Alice can revoke
│ my: [X,Y,Z] │ │
Copy link
Member Author

Choose a reason for hiding this comment

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

✂️ my:

README.md Outdated
| `exp` | `Number` | Expiration UTC Unix Timestamp (valid until) | Yes |
| `nnc` | `String` | Nonce | No |
| `fct` | `Json[]` | Facts (asserted, signed data) | No |
| `my` | `Json[]` | Delegation by parenthood | No |
Copy link
Member Author

Choose a reason for hiding this comment

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

✂️ my:

README.md Outdated
Comment on lines 475 to 516
## 5.2 Top

The "top" (or "super user") ability MUST be denoted `*/*`. The top ability grants access to all other capabilities for the specified resource, across all possible namespaces. Top corresponds to an "all" matcher, whereas [delegation](#51-ucan-delegation) corresponds to "any" in the UCAN chain. The top ability is useful when "linking" agents by delegating all access to resource(s). This is the most powerful ability, and as such it SHOULD be handled with care.

```
┌───────┐
│ │
│ */* │
│ │
└▲──▲──▲┘
│ │ │
┌────────────────────────────┘ │ └────────────────────┐
│ │ │
┌────┴────┐ ┌────┴─────┐ ┌───┴───┐
│ │ │ │ │ │
│ msg/* │ │ crud/* │ │ ... │
│ │ │ │ │ │
└─▲────▲──┘ └─▲──────▲─┘ └───────┘
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
┌───────────┴┐ ┌─┴─────────────┐ ┌──────────┴──┐ ┌─┴─────────────┐
│ │ │ │ │ │ │ │
│ msg/send │ │ msg/receive │ │ crud/read │ │ crud/mutate │
│ │ │ │ │ │ │ │
└────────────┘ └───────────────┘ └─────────────┘ └─▲─────▲─────▲─┘
│ │ │
┌──────┘ │ └──────┐
│ │ │
│ │ │
┌────────────┴──┐ ┌───────┴───────┐ ┌──┴─────────────┐
│ │ │ │ │ │
│ crud/create │ │ crud/update │ │ crud/destroy │
│ │ │ │ │ │
└───────────────┘ └───────────────┘ └────────────────┘
```

### 5.2.1 Bottom

In concept there is a "bottom" ability ("none" or "void"), but it is not possible to represent in an ability. As it is merely the absecnce of any ability, it is not possible to construct a capability with a bottom ability.

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 realized that we actually do need a top ability for a bunch of linking use cases at Fission (and I believe Bluesky), and that it likely does need to live in the core spec. I had removed it a few days ago after seeing how DAG House is approaching their modelling. This does not alter how they need to think about their abilities at all, and they do not need to adopt */*.

I expanded on the explanation & diagram after explaining the feature to Irakli a few days ago. The syntax is also changed to be consistent with the */* pattern that we see showing up in the wild.

Copy link
Contributor

@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.

Thank you so much @expede for all the work & I apologize for the delay.

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
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
delegatescheme = "as:" did ":" kind
kind = "*" / <scheme>
own = "own://" <did-subject> "/" scheme-scope
scheme-selector = "*" / <scheme>
Copy link
Contributor

Choose a reason for hiding this comment

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

@expede If I recall correctly you said motivation for the own:// protocol was due to the fact that did:key: can't have paths in them ? However I was unable to find that restriction & was wondering if maybe that is invalid assumption ?

I was also thinking that:

  1. Query params could probably used to restrict what's delegated from one agent to the other.
  2. own: could be subsumed by ucan:did:key:zKey instead so we avoid reserving more than one protocol scheme.

Copy link
Member Author

Choose a reason for hiding this comment

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

There's two things:

  1. UCAN isn't restricted to did:key. As you mention, the DID spec doesn't restrict the path segment, so any DID method can define path segment, breaking the proposed solution
  2. Sure, we could use the ucan: scheme instead. Any thoughts pro/con on using a subscheme?

Maybe I can borrow you in person while we're in person the next few days. I'll ping you on Discord.

@expede
Copy link
Member Author

expede commented Aug 31, 2022

@Gozala several your comments seems to be on old code — not sure what's happening there. For example:

Screen Shot 2022-08-31 at 10 05 41

Copy link
Member

@hugomrdias hugomrdias left a comment

Choose a reason for hiding this comment

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

Left just one inline suggestion for a rendering problem so assume LGTM and approval after that fix.

README.md Outdated Show resolved Hide resolved
Co-authored-by: Hugo Dias <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Principal IDs and signature verification
9 participants