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-rc.1 #173

Merged
merged 88 commits into from
Aug 7, 2024
Merged

v1.0-rc.1 #173

merged 88 commits into from
Aug 7, 2024

Conversation

expede
Copy link
Member

@expede expede commented Oct 9, 2023

@cla-bot cla-bot bot added the cla-signed label Oct 9, 2023
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.

At the high level it looks good and improves on some pain points we've experienced. That said, reading this:

  1. I'm no longer sure what the structure of the UCAN looks like any more perhaps even one example somewhere would help.
  2. I think imposing certain structure on commands / abilities would really simplify things yet will not prevent anyone to go with a different approach if they choose so, they'll only loose ability to leverage certain tooling that will become possible.
  3. Given significant changes here, I would be more comfortable calling this 0.20 or something and let it settle before we mark it 1.0 or 1.0-rc
  4. Document often refers to proof chains, yet leaves a lot of ambiguity what they are. I find that confusing, UCANs without proofs feel more like certificates that you can chain into authorization. I feel like it would be good to either call that out explicitly or avoid referring to proof chains

README.md 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 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 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 Show resolved Hide resolved
@expede expede changed the title DRAFT! High Level Spec Top-Level Spec Nov 2, 2023
@expede expede marked this pull request as ready for review November 2, 2023 23:05
UCANs (and other forms of PKI) depend on the ambient authority of the owner of each resource. This means that the discharging agent must be able to verify the root ownership at decision time. The rest of the chain in-between is self-certifying.
## Security Considerations

Each UCAN includes an assertions of what it is allowed to do. "Proofs" are positive evidence (elsewhere called "witnesses") of the possession of rights. They are cryptographically verifiable chains showing that the UCAN issuer either claims to directly own a resource, or that it was delegated to them by some claimed owner. In the most common case, the root owner's ID is the only globally unique identity for the resource.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Each UCAN includes an assertions of what it is allowed to do. "Proofs" are positive evidence (elsewhere called "witnesses") of the possession of rights. They are cryptographically verifiable chains showing that the UCAN issuer either claims to directly own a resource, or that it was delegated to them by some claimed owner. In the most common case, the root owner's ID is the only globally unique identity for the resource.
Each UCAN includes assertions of what it is allowed to do. "Proofs" are positive evidence (elsewhere called "witnesses") of the possession of rights. They are cryptographically verifiable chains showing that the UCAN issuer either claims to directly own a resource, or that it was delegated to them by some claimed owner. In the most common case, the root owner's ID is the only globally unique identity for the resource.

"an" looks unneeded here.


Merging capability authorities MUST follow set semantics, where the result includes all capabilities from the input authorities. Since broader capabilities automatically include narrower ones, this process is always additive. Capability authorities can be combined in any order, with the result always being at least as broad as each of the original authorities.
Unless explicitly stated, the Resource of a UCAN MUST be the Subject.

Choose a reason for hiding this comment

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

I don't understand where and how any other state of affairs could be explicitly stated? Do you mean

Suggested change
Unless explicitly stated, the Resource of a UCAN MUST be the Subject.
Unless all expected recipients of a UCAN will understand how the Subject of a UCAN relates to the Resource being authorized because this relationship is explicitly clarified out-of-band, it can be assumed by all parties that a UCAN's subject is coterminous with the Resource authorized by that UCAN.

? I assume not, but if you asked me to make that sentence more verbose, this is what I would come up with, which feels like a very wrong guess.

| Issuer | The Principal of the current UCAN. Listed in the `iss` field |
| Owner | A Subject that controls some external resource |
| Principal | An agent identified by DID (listed in a UCAN's `iss` or `aud` field) |
| Revoker | The Issuer listed in a proof chain that revokes a UCAN |
Copy link

@bumblefudge bumblefudge Aug 6, 2024

Choose a reason for hiding this comment

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

There is only one revoker per UCAN, but a chain has any many possible revokers as there are links in the chain, right? This sentence makes it sound like every chain has ONE revoker, rather than one revoker per UCAN/link in a chain.

Suggested change
| Revoker | The Issuer listed in a proof chain that revokes a UCAN |
| Revoker | The Issuer of each UCAN listed in a proof chain which revokes that UCAN and subsequent chain |

| Executor | The Agent that actually performs the action described in an invocation |
| Invoker | A Principal that requests an Executor perform some action that uses the Invoker's authority |
| Issuer | The Principal of the current UCAN. Listed in the `iss` field |
| Owner | A Subject that controls some external resource |

Choose a reason for hiding this comment

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

Suggested change
| Owner | A Subject that controls some external resource |
| Owner | A Subject that controls some external resource |

| Agent | The general class of entities and principals that interact with a UCAN |
| Audience | The Principal delegated to in the current UCAN. Listed in the `aud` field |
| Executor | The Agent that actually performs the action described in an invocation |
| Invoker | A Principal that requests an Executor perform some action that uses the Invoker's authority |

Choose a reason for hiding this comment

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

Suggested change
| Invoker | A Principal that requests an Executor perform some action that uses the Invoker's authority |
| Invoker | A Principal that requests an Executor perform some action that uses the Invoker's authority |


The capability authority is the total rights of the authorization space down to the relevant volume of authorizations. Individual capabilities MAY overlap; the authority is the union. Except for [rights amplification], every unique delegation MUST have equal or narrower capabilities from their delegator. Inside this content space, you can draw a boundary around some resource(s) (their type, identifiers, and paths or children) and their capabilities.
The Issuer (`iss`) and Audience (`aud`) can be conceptualized as the sender and receiver (respectively) of a postal letter. Every UCAN MUST be signed with the private key associated with the DID in the `iss` field.

Choose a reason for hiding this comment

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

Suggested change
The Issuer (`iss`) and Audience (`aud`) can be conceptualized as the sender and receiver (respectively) of a postal letter. Every UCAN MUST be signed with the private key associated with the DID in the `iss` field.
The Issuer (`iss`) and Audience (`aud`) can be conceptualized as the sender and receiver (respectively) of a postal letter. Every UCAN MUST be signed with the private key associated with the DID in the `iss` field.
Note that the UCAN system assumes a 1:1 relationship between DID URLs and public keys, and all examples are given using `did:key`, where bare DIDs are resolvable directly and deterministically to single keys. For DID methods that support multiple keys for a given DID, verification-specific [DID URLs using fragment identifiers](https://www.w3.org/TR/did-core/#fragment) MUST be used for `iss` and `aud` values to preserve interoperability; non-key-based `verificationMethod`s MUST NOT be used, for the same reason.

I think I promised this as a PR over a year ago, I'm realizing as I write this up now 🙈


In an ideal world, a single algorithm (Ed25519) would be available everywhere. For many historical reasons, P-256 and `secp256k1` are the only practical options for many applications, such as the [WebCrypto API] and many cryptocurrency wallets. A design goal of UCAN is to leverage existing public key infrastructure (PKI), and supporting these three algorithms achieves that goal. Requiring multiple signature types for broad interoperability is not an unusual design choice; for example, [JWT] supports multiple signature algorithms for a similar reason.

The NIST report on post-quantum computing will also be released in the next few months, so we anticipate a shift to new algorithms in the medium-term.

Choose a reason for hiding this comment

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

Which report do you mean? "The" report came out in 2016, but I assume you mean a more definitive one?
https://csrc.nist.gov/Projects/post-quantum-cryptography/publications


For more on this representation, please refer to [canonical collections].
The Subject and Command fields are REQUIRED. Any non-normative extensions are OPTIONAL.

Choose a reason for hiding this comment

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

are all policies "non-normative extensions"? are any other fields? OPTIONAL for implementations to handle? Dropped if unknown? I know this is all stated in the delegation spec, but just speaking as a reader, a tiny bit more detail, although redundant, might be helpful here for high-level readers!

Choose a reason for hiding this comment

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

also, are they "Arguments" now? I am seeing links elsewhere in this document to [Arguments] but there is no ### Arguments section (or for that matter a ### Policy or ### Extensions section, either!), so probably time to add one.


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] 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.
The wildcard ability grants access to all other capabilities for the specified resource, across all possible namespaces. The wildcard ability is useful when "linking" agents by delegating all access to another device controlled by the same user, and that should behave as the same agent. It is extremely powerful, and should be used with care. Among other things, it permits the delegate to update a Subject's mutable DID document (change their private keys), revoke UCAN delegations, and use any resources delegated to the Subject by others.

Choose a reason for hiding this comment

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

i'm sorry what's this about a DID Document? that is an implementation detail (there's nothing about DID documents inherent to the UCAN spec, is there?), yet it is stated as a generality... i'd remove, or at least phrase as a possible example...


# 6. Validation
The `/ucan` Command namespace MUST be reserved. This MUST include any ability string matching the regex `^ucan\/.*`. This is important for keeping a space for community-blessed Commands in the future, such as standard library Commands, such as [Revocation].

Choose a reason for hiding this comment

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

Suggested change
The `/ucan` Command namespace MUST be reserved. This MUST include any ability string matching the regex `^ucan\/.*`. This is important for keeping a space for community-blessed Commands in the future, such as standard library Commands, such as [Revocation].
The `/ucan` Command namespace MUST be reserved. This MUST include any ability string matching the regex `^ucan(\/(^\m\/)+)+`. This is important for keeping a space for community-blessed Commands in the future, such as standard library Commands, such as [Revocation].

I'm no regex wizard but I'm guessing this regex is older than the prohibition on trailing /s, which this newer, uglier regex bans.

Also, I couldn't tell if /ucan was supposed to be a valid command (or a valid blank-check for future stdlib commands), but if so, that last + (1 or more) should be a * (0 or more).

rootAud(aud: Bob)
rootCap("cap: (Storage, crud/*)")
end
This field SHOULD NOT be used to sign arbitrary data, such as signature challenges. See the [`meta`][Metadata] field for more.
Copy link

@bumblefudge bumblefudge Aug 6, 2024

Choose a reason for hiding this comment

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

Suggested change
This field SHOULD NOT be used to sign arbitrary data, such as signature challenges. See the [`meta`][Metadata] field for more.
This field SHOULD NOT be used to sign arbitrary data, such as signature challenges. See the [`meta`][#metadata] field for more.


If any of the following criteria are not met, the UCAN MUST be considered invalid.
Attenuation is the process of constraining the capabilities in a delegation chain. Each direct delegation MUST either directly restate or attenuate (diminish) its capabilities.

Choose a reason for hiding this comment

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

Suggested change
Attenuation is the process of constraining the capabilities in a delegation chain. Each direct delegation MUST either directly restate or attenuate (diminish) its capabilities.
Attenuation is the process of constraining the capabilities in a delegation chain. Each direct delegation MUST either explicitly restate or attenuate (diminish) its capabilities.


A UCAN is valid inclusive from the `nbf` time and until the `exp` field. If the current time is outside of these bounds, the UCAN MUST be considered invalid. When setting these bounds, a delegator or invoker SHOULD account for expected clock drift. Use of time bounds this way is called "timely invocation."
Note that if an instance cannot dereference a CID at runtime, the UCAN MUST fail validation. This is consistent with the [constructive semantics] of UCAN.
Copy link

@bumblefudge bumblefudge Aug 6, 2024

Choose a reason for hiding this comment

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

Note that this is the first mention of a CID in the entire high-level spec, without a preceding normref or definition.

Editorial nitpicking aside, I think it might be clearer to refer to them as links in this and other section (which, in IPLD, are effectively just IPFS CIDs) rather than refer to them as CIDs, because what matters is that they are identifiers they can't be defererenced, not anything about their nature as content identifiers or multiformats, etc etc. (I.e., I can imagine an RDF/JSON-LD version of this where the same link-dereferenceability rule applies to DID URLs, or HTTPS URLS, or some other kinds of dereferenceable URIs...)

Choose a reason for hiding this comment

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

For example:

Suggested change
Note that if an instance cannot dereference a CID at runtime, the UCAN MUST fail validation. This is consistent with the [constructive semantics] of UCAN.
Note that if a UCAN includes links in the form of [IPFS CIDs][CID] to subgraphs, and a parsing implementation cannot expand the full graph because one or more of these links cannot be dereferenced at runtime, then the UCAN MUST fail validation. This is consistent with the [constructive semantics] of UCAN.

README.md Outdated
[capabilities]: https://en.wikipedia.org/wiki/Object-capability_model
[caps as keys]: http://www.erights.org/elib/capability/duals/myths.html#caps-as-keys
[certificate capability model]: http://wiki.erights.org/wiki/Capability-based_Active_Invocation_Certificates

Choose a reason for hiding this comment

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

Suggested change
[certificate capability model]: http://wiki.erights.org/wiki/Capability-based_Active_Invocation_Certificates
[certificate capability model]: http://wiki.erights.org/wiki/Capability-based_Active_Invocation_Certificates
[CID]: https://docs.ipfs.tech/concepts/content-addressing/

Unless the uglier, raw github definition seems more appropriate or canonical for whatever reason?
https://github.com/multiformats/cid

README.md Show resolved Hide resolved

Alice delegates access to Bob. Bob then redelegates to Carol. Carol invokes the UCAN as part of a REST request to a compute service. To do this, she MUST both provide proof that she has access (the UCAN chain), and MUST delegate access to the discharging compute service. The discharging service MUST check that the root issuer (Alice) is in fact the owner (typically the creator) of the resource. This MAY be listed directly on the resource, as it is here. Once the UCAN chain and root ownership are validated, the storage service performs the write.
The OPTIONAL `meta` field contains a map of arbitrary metadata, facts, and proofs of knowledge. The enclosed data MUST be self-evident and externally verifiable. It MAY include information such as hash preimages, server challenges, a Merkle proof, dictionary data, etc.
Copy link

@bumblefudge bumblefudge Aug 6, 2024

Choose a reason for hiding this comment

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

Suggested change
The OPTIONAL `meta` field contains a map of arbitrary metadata, facts, and proofs of knowledge. The enclosed data MUST be self-evident and externally verifiable. It MAY include information such as hash preimages, server challenges, a Merkle proof, dictionary data, etc.
The OPTIONAL `meta` field contains a map of arbitrary metadata, facts, and proofs of knowledge. The enclosed data SHOULD be self-evident and externally verifiable. It MAY include information such as hash preimages, server challenges, a Merkle proof, dictionary data, etc.

It feels like this MUST is untestable, and is more like an instruction to [the intentions of users of] UCAN-generating/encoding implementations than anything that could be included in a conformance test? It might be better phrased as a consuming behavior, i.e., "Validators MUST NOT consider the contents when proofing UCAN invocation".

corner-case: do CIDs in metadata have to be dereferenceable at runtime as well? or does their being unmeaningful trump their being IPLD 😄

## 2.8 Attenuation

Attenuation is the process of constraining the capabilities in a delegation chain.
Please see the [Cryptosuite] section for more detail on DIDs.

Choose a reason for hiding this comment

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

Narrator: but there was no more detail on DIDs there.

Choose a reason for hiding this comment

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

Suggested change
Please see the [Cryptosuite] section for more detail on DIDs.
Please see the [Cryptosuite](#cryptosuite) section for more detail on DIDs.

"example.com": "abcdef",
"another.example.net": "12345"
},
"sha3_256": {
Copy link

@bumblefudge bumblefudge Aug 6, 2024

Choose a reason for hiding this comment

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

not SHA-256, i.e. SHA-2? or is that deliberate?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is an example of putting in arbitrary data. It literally doesn't matter


A UCAN token MUST be referenced as a [base32] [CIDv1]. [SHA2-256] is the RECOMMENDED hash algorithm.
> [!NOTE]
> All CIDs encoded as above start with the characters `zdpu`.

Choose a reason for hiding this comment

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

If they're canonically DAG-CBOR why is the multibase needed, as opposed to staying in binary? Maybe I've been talking to the wrong people but I thought CIDv1 was canonically binary and optionally multibased, so it feels like an extra roundtrip to multibase it and then drop back down to CBOR...


Except for rights amplification (below), each capability delegation MUST have equal or narrower capabilities from its proofs. The time bounds MUST also be equal to or contained inside the time bounds of the proof's time bounds. This lowering of rights at each delegation is called "attenuation."
All UCANs MUST be canonically encoded with [DAG-CBOR] for signing. A UCAN MAY be presented or stored in other [IPLD] formats (such as [DAG-JSON]), but converted to DAG-CBOR for signature validation.

Choose a reason for hiding this comment

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

I feel like the { "/" : { "bytes": "... notation needs to be explained a little here, rather than assuming the reader both wants to and can reasonably click that "DAG-CBOR" link and come back 10 minutes later knowing what IPLD is, if they don't already... because if I am confused, who is your target reader 😏


The [`0x55` raw data][raw data multicodec] codec MUST be supported. If other codecs are used (such as [`0x0129` `dag-json` multicodec][dag-json multicodec]), the UCAN MUST be able to be interpreted as a valid JWT (including the signature).
The resolution of these addresses is left to the implementation and end-user, and MAY (non-exclusively) include the following: local store, a distributed hash table (DHT), gossip network, or RESTful service.

Choose a reason for hiding this comment

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

Redundant, sure, but here might be a good place to remind the reader that a validator MUST fail verification of a UCAN with subgraphs linked by CID that do not dereference at time of consumption of invocations.


Revocations MAY be deleted once the UCAN that they reference expires or otherwise becomes invalid via its proactive mechanisms.
Aside from revocation, capability validation is idempotent. Marking a CID (or capability index inside that CID) as valid acts as memoization, obviating the need to check the entire structure on every validation. This extends to distinct UCANs that share a proof: if the proof was previously reviewed and is not revoked, it is RECOMMENDED to consider it valid immediately.
Copy link

@bumblefudge bumblefudge Aug 6, 2024

Choose a reason for hiding this comment

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

Should that by "Aside from revocation and expiration,..." ?

I am also confused by the corner case mentioned here by Gozala:

Let's say Alice delegates to Bob a capability /crud/ over a hard disk, then Bob sends Carol (me) a capability /crud/write/. Before I go to invoke it at Alice's hard disk, Alice's original parent cap expired or was revoked. Bob sends me a new sub-delegation identical except for having a fresher parent. That's a different token, right? This idempotency stuff doesn't apply because if it's a different chain, it's a different token?


### 6.6.1 Example
Revocation is irreversible. Suppose the validator learns of revocation by UCAN CID. In that case, the UCAN and all of its derivatives in such a cache MUST be marked as invalid, and all validations immediately fail without needing to walk the entire structure.

Choose a reason for hiding this comment

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

I'd love for "Suppose the validator learns of revocation by UCAN CID" to be expanded a bit, I'm having trouble supposing from that very high-level summary 😅

@bumblefudge
Copy link

Forgive the billion little comments, few of them are worth discussing in further detail, mostly just idle suggestions. Is merging this blocked by anything? Just waiting for invocation to go to v1rc1?

| `cmd` | `String` | Yes | The [Command] to eventually invoke |
| `args` | `{String : Any}` | Yes | Any [Arguments] that MUST be present in the Invocation |
| `nonce` | `Bytes` | Yes | Nonce |
| `meta` | `{String : Any}` | No | [Meta] (asserted, signed data) — is not delegated authority |

Choose a reason for hiding this comment

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

Maybe break out the non-required fields into a separate table below, since all of this is under MUST CONTAIN?

And throw iat in there, too?

Copy link
Member Author

Choose a reason for hiding this comment

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

The rationale is that iat is not in the delegation spec since it's not particularly helpful for delegation. Invocation does have an iat, so it's not a common field across all UCAN formats

@expede expede merged commit 1c64556 into main Aug 7, 2024
3 checks passed
@expede expede deleted the high-level branch August 7, 2024 00:25
@expede expede changed the title Top-Level Spec v1.0-rc.1 Aug 7, 2024
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.

4 participants