-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
v1.0.0-rc.1 #2
base: main
Are you sure you want to change the base?
v1.0.0-rc.1 #2
Conversation
Thanks for the feedback @smoyer64 ! Responses inline: Quickly jumping to the end first
Thank you for the deep engagement with the material! I think other than the question about how strictly we adhere to jq, I'd like to implement the rest of your comments! 🙏
PR merged! Thanks :)
Yes, as Irakli responded earlier, we do have some divergences from jq. We think that they're well motivated ( #5 ) , but they have already bitten both you and me, so perhaps we should rethink that.
Agreed ✅ Will fix (DONE)
This is one of the examples that we chose to diverge on. In short: jq is (largely) a parser that processes streams, and UCAN policies are a policy language that operate on static data. The security implications of permissive behaviour may be significant, and we can always get the There's also a few cases of expressivity, e.g. distinguishing between a
Interesting! Can you expand on this?
🤔 Perhaps. jq operates on streams, and is more permissive in how it treats things like assertion violation (e.g. when a field is not present), which may not be appropriate for an access control context.
Could you expand? I'm not certain that ours is filtering in the same sense as jq filters on streams (or in the sense that you
Sure, let's switch it to "Optional" ✅ (DONE)
If helpful, we could also switch to IPLD Schema if that's better for this purpose than ANBF. I was trying to avoid IPFS Schema since it has its own set of design issues.
Yes, it does depend on the other design decisions for certain. I'm not as confident in the strategy of generating a parser directly since you'll need to reserialise the CBOR to JSON for this to work, right? That could be expensive on every request.
I'll flip the switch on the Rust implementation momentarily (DONE). It needs a few tweaks to come in line with your and Irakli's comments, but a version of it was being used right at the end of Fission.
We have two parallel implementations: JS and Rust. |
Indeed, that's how the Rust code works.
Will update the spec ✅ |
@smoyer64 I pushed the branch directly to the |
I'm happy to concede that the deviations from strict compatibility with
This example from the
Yes and I'm happy to see that @alanshaw has written a tokenizer/parser/matcher that works on the IPLD nodes.
Awesome! This will make it easier to decipher the spec - should I feed anything I think are ambiguities back into PRs? |
README.md
Outdated
| `iss` | `DID` | Yes | Issuer DID (sender) | | ||
| `aud` | `DID` | Yes | Audience DID (receiver) | | ||
| `sub` | `DID \| null` | Yes | Principal that the chain is about (the [Subject]) | | ||
| `cmd` | `String` | Yes | The [Command] to eventually invoke | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any chance to make that cmd
a [String]
, so that multiple capability can be delegated with the same payload?
Unless I missed something, if a (larger) service wants to delegate a set of capabilities to a user, it might not be possible to express that with a nice wildcard. Instead, you'd have a list of command: /foo/*, /bar/baz, /bar/boz, ...
.
As I understand, with cmd
being a String
(and not allowing comma-separated value I assume), this has the following consequences:
- a separate payload need to be issued and sign for each of the capabilities
- the receiver (audience) need to handle multiple delegation: much more complex UX/DX and logic necessary on the client side
- much larger token overall, especially as the signatures are duplicated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe better, have it be a [Capability]
, so that one policy remains attached to one command neatly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We did essentially [Capability]
previously, and it had some ugly tradeoffs in practice that we heard complaints about for years until we removed. Some people liked it, but it made the token more complex, and saved way less space than you'd think. It also forces you to pass around (and leak!) a bunch of extra capabilities that don't apply to, it's way more complex to do revocations that target only one capability, etc.
The one thing that I do want to recover from [Capability]
is fewer signatures (as always: crypto can be expensive). The solution there is to adopt batch signatures, which are flagged for a future version of Varsig. Basically build a Merkle tree of things to sign, sign the root, and include the Merkle proof to your token in the signature field.
|
||
Policies are structured as trees. With the exception of subtrees under `any`, `or`, and `not`, every leaf MUST evaluate to `true`. | ||
|
||
A Policy is an array of statements. Every statement MUST take the form `[operator, selector, argument]` except for negation which MUST take the form `["not", statement]`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless I'm missing something, and
and or
also have that 2-tuple form.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, those two are actually N-tuple, with N >= 2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, they are 2-tuple, but the ABNF grammar is wrong
|
||
```js | ||
// Data | ||
{ name: "Katie", age: 35, nationalities: ["Canadian", "South African"] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{ name: "Katie", age: 35, nationalities: ["Canadian", "South African"] } | |
{ "name": "Katie", "age": 35, "nationalities": ["Canadian", "South African"] } |
// Data | ||
{ name: "Katie", age: 35, nationalities: ["Canadian", "South African"] } | ||
|
||
["and", []] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm not mistaken, all those policy example should be wrapped with [ <example goes here> ]
, otherwise there are not legal as per the syntax
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose those are statements, not policies, but that's a bit confusing.
["not", | ||
["and", [ | ||
["==", ".name", "Katie"], | ||
["==", ".nationalities", ["American"]] // ⬅️ false | ||
]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
["not", | |
["and", [ | |
["==", ".name", "Katie"], | |
["==", ".nationalities", ["American"]] // ⬅️ false | |
]] | |
["not", | |
["and", [ | |
["==", ".name", "Katie"], | |
["==", ".nationalities", ["American"]] // ⬅️ false | |
]] | |
] |
|----------|---------------------|---------------------------------------| | ||
| `like` | `Selector, Pattern` | `["like", ".email", "*@example.com"]` | | ||
|
||
Glob patterns MUST only include one specicial character: `*` ("wildcard"). There is no single character matcher. As many `*`s as desired MAY be used. Non-wildcard `*`-literals MUST be escaped (`"\*"`). Attempting to match on a non-string MUST return false and MUST NOT throw an exception. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is zero *
allowed? Does that means exactly one *
or at most one *
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the next person, I read that wrong:
Glob patterns MUST only include one special character
means: the grammar only has one special character (*
), but that character is allowed multiple times in the same pattern: foo*bar*baz
is valid.
Something that's not clear to me (but maybe I missed it): is it valid to overdelegate abilities? Can A delegate That is, in essence, does Operating like the Powerline would be a lot more powerful, but also puts a bit more burden on the implementer to calculate the correct effective capability. |
This is a late binding decision — it happens at invocation time, not delegation time. You provide the path of delegations to the invocation, and it takes the minimal subset of all delegations by applying all policies to the invocation (you need to pass all policies in your stated proof chain) Another way of thinking about this is that if you think of delegations as edges in an authority graph, where authority "flows" between agents. You can arrive at that edge from an of a number of earlier paths; and you have to state which one it is when invoking so that it's unambiguous what your intent is and how to prove that you can do that. If your upstream path is more powerful, then the less powerful edge attenuates it. As a best practice, you SHOULD restate your intended authority level at each delegation. This is a tradeoff in the design that makes it significantly easier to recover if an upstream delegation (which may be |
README.md
Outdated
| Identity | `.` | Take the entire argument | | ||
| Dotted field name | `.foo`, `.bar0_` | Shorthand for selecting in a map by key (with exceptions, see below) | | ||
| Unambiguous field name | `["."]`, `["$_*"]` | Select in a map by arbitrary key | | ||
| Collection values | `[]` | Expands out all of the children that match the remaining path FIXME double check with the code | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you clarify what that does and/or provide an example?
I may get pilloried for this version. WIP, obviouslyPreview 📚
Okay, this version switches to IPLD. This makes it much easier to not need a IPLD version off to the side, and many teams that have adopted UCAN already use IPLD somewhere in their stack. There is a contingent of people that feel strongly in favour of JWT for a variety of reasons. I also defended the JWT strategy for a long time, beacuse I had many first-hand converstaions of "I need to sell this to management, please tell me it's a JWT and not some inscrutable binary format".
A few things have changed:
I believe that this proposal makes writing both UCAN Delegations and libraries much easier and more comprehensible. It also lowers our maintenance burden between multiple formats.
Changelog
Metadata
1.0.0-rc.1
Structure
ucan-wg/revocation
ucan-wg/invocation
ucan/*
(moving toucan-wg/ucan-uri
)ucan-wg/ucan-uri
prf
field toucan-wg/invocation
+ add to top-levelucan-wg/spec
Time
exp
nullableProse
6[now] 5, that you only invalidate single capabilities; not everything