diff --git a/.clabot b/.clabot new file mode 100644 index 0000000..d504977 --- /dev/null +++ b/.clabot @@ -0,0 +1,15 @@ +{ + "contributors": [ + "appcypher", + "b5", + "bgins", + "expede", + "matheus23", + "QuinnWilton", + "bmann", + "dholms", + "gozala", + "gobengo", + "nicobao" + ] +} diff --git a/.custom-words.txt b/.custom-words.txt new file mode 100644 index 0000000..86465f0 --- /dev/null +++ b/.custom-words.txt @@ -0,0 +1,240 @@ +ACL +ACLs +AlicePhone +AliceRoot +Attenuations +Aud +Auth +AuthorityA +AuthorityB +BCP +BT +Bluesky +BxZ +CBOR +CIDs +CIDv +CNAME +CRDT +CRDTs +Canonicalization +Compositionality +DAG +DAGs +DHT +DID's +DIDs +DNF +DNS +DNSLinks +DT +Datalog +ECDSA +EL +EdDSA +GLVVQR +GUID +Golang +Gozalishvili +HEHYSF +HMACs +Haus +Holmgren +IPLD +Invoker's +Irakli +JSON +JWT +JWTs +Karp +Kleppmann +Krüger +LD +Lemmer +Meiklejohn +Memoized +Merkle +Mikael +MkiTBz +OCAP +OCapN +PITM +PKI +POLA +Philipp +Pseudocode +RBAC +RESTful +RL +RSA +RSM +Redelegating +Redelegation +Revoker +SDSI +SHA +SPKI +ScopeA +ScopeB +Seitan +SignatureBytes +Subschemes +TXT +TypeScript +UCAN +UCAN's +UCANs +URI +URIs +Vandevelde +Varsig +WG +WebNative +Webber +ZCAP +Zelenka +adoptability +al +alice +args +async +attenuations +aud +auth +autonumber +baz +bene +blockchain +cachability +cacheability +cid +codec +codecs +cond +const +const +const +const +crudGraph +crypto +cryptographic +cryptographically +del +delegable +delegationChain +delegator +dereference +disambiguates +disjunct +djdX +dns +ensureProofExp +ensureProofExp +ensureProofNbf +ensureProofNbf +ensureTime +ensureTimeBounds +ensureTimeBounds +enums +escelation +et +ewvi +ewvi +extensibility +extractable +filesystem +fooey +forEach +getUcan +hawaii +hoc +https +iff +init +inlining +interconnectivity +interpretable +inv +invoker +iss +js +json +lifecycle +lockboxes +mDooWp +mailto +matcher +matchers +memoization +modelled +monday +msg +msgGraph +multicodec +namespace +namespaced +namespaces +nbf +nbf +nbsp +nbspAlice +nbspDan +nestable +nonces +nota +num +numerics +nxzyoun +nxzyoun +ocap +oiz +oiz +pathing +pcec +plaintext +plc +plc +potencies +pre +preimages +prf +quG +rc +reauthorizations +recommentations +redelegate +redelegates +requestors +rootAud +rootCap +rootIss +runtime +scalable +sdarnit +sequenceDiagram +significand +situationally +stateful +subdelegate +subgraph +subscheme +tradeoffs +trustless +trustlessly +ucan +un +unary +unforgeability +unresolvable +uri +url +validatable +validator +validator's +validators +verifiability +wnfs +xyz +ymuepAQ +zhxrhs +zhxrhs diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..628788e --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +# @global-owner1 and @global-owner2 will be requested for +# review when someone opens a pull request. +* @expede @matheus23 @gozala @dholms diff --git a/.github/workflows/linkcheck.cfg.json b/.github/workflows/linkcheck.cfg.json new file mode 100644 index 0000000..1d3eb1e --- /dev/null +++ b/.github/workflows/linkcheck.cfg.json @@ -0,0 +1,10 @@ +{ + "ignorePatterns": [ + { + "pattern": "https://share.ansi.org/Shared%20Documents/Standards%20Activities/American%20National%20Standards/Procedures,%20Guides,%20and%20Forms/2020_ANSI_Essential_Requirements.pdf" + }, + { + "pattern": "https://share.ansi.org/Shared%20Documents/Standards%20Activities/American%20National%20Standards/Procedures,%20Guides,%20and%20Forms/2020_ANSI_Essential_Requirements.pdf" + } + ] +} diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml new file mode 100644 index 0000000..b5a0a32 --- /dev/null +++ b/.github/workflows/linkcheck.yml @@ -0,0 +1,19 @@ +name: Check Markdown links + +on: + push: + branches: + - main + pull_request: + +jobs: + markdown-link-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - uses: gaurav-nelson/github-action-markdown-link-check@v1 + with: + use-quiet-mode: "yes" + check-modified-files-only: "yes" + base-branch: "main" + config-file: "./.github/workflows/linkcheck.cfg.json" diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml new file mode 100644 index 0000000..06710ca --- /dev/null +++ b/.github/workflows/spellcheck.yml @@ -0,0 +1,12 @@ +name: Spellcheck Action +on: push + +jobs: + build: + name: Spellcheck + runs-on: ubuntu-latest + steps: + # The checkout step + - uses: actions/checkout@master + - uses: rojopolis/spellcheck-github-actions@0.24.0 + name: Spellcheck diff --git a/.spellcheck.yml b/.spellcheck.yml new file mode 100644 index 0000000..12935cb --- /dev/null +++ b/.spellcheck.yml @@ -0,0 +1,26 @@ +matrix: +- name: Markdown + aspell: + lang: en + d: en_US + dictionary: + encoding: utf-8 + wordlists: [".custom-words.txt"] + pipeline: + - pyspelling.filters.markdown: + - pyspelling.filters.html: + comments: false + ignores: + - code + - pre + - pyspelling.filters.context: + context_visible_first: true + escapes: \\[\\`~] + delimiters: + - open: '(?s)^(?P *`{3,})$' + close: '^(?P=open)$' + - open: '(?P`+)' + close: '(?P=open)' + sources: + - 'README.md' + default_encoding: utf-8 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..a94f38d --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,133 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +hello@brooklynzelenka.com, philipp@fission.codes, or hello@fission.codes. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..30dfdd6 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,13 @@ +# Contributing + +When contributing to this repository, please first discuss the change you wish to make via issue, +discussion, or any other method with the owners of this repository before making a change. + +Please note we have a code of conduct, please follow it in all your interactions with the project. + +## Pull Request Process + +1. Ensure that you have signed the CLA: in a separate PR, add your information to + the [Notices](./Notices.md), and [CLA Bot](./.clabot). +2. Increase the version numbers in any examples files and the README.md to the new version that this + Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). diff --git a/Community_Specification_License-v1.md b/Community_Specification_License-v1.md new file mode 100644 index 0000000..e49e871 --- /dev/null +++ b/Community_Specification_License-v1.md @@ -0,0 +1,99 @@ +# Community Specification License 1.0 + +**The Purpose of this License.** This License sets forth the terms under which 1) Contributor will participate in and contribute to the development of specifications, standards, best practices, guidelines, and other similar materials under this Working Group, and 2) how the materials developed under this License may be used. It is not intended for source code. Capitalized terms are defined in the License’s last section. + +**1. Copyright.** + +**1.1. Copyright License.** Contributor grants everyone a non-sublicensable, perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as expressly stated in this License) copyright license, without any obligation for accounting, to reproduce, prepare derivative works of, publicly display, publicly perform, and distribute any materials it submits to the full extent of its copyright interest in those materials. Contributor also acknowledges that the Working Group may exercise copyright rights in the Specification, including the rights to submit the Specification to another standards organization. + +**1.2. Copyright Attribution.** As a condition, anyone exercising this copyright license must include attribution to the Working Group in any derivative work based on materials developed by the Working Group. That attribution must include, at minimum, the material’s name, version number, and source from where the materials were retrieved. Attribution is not required for implementations of the Specification. + +**2. Patents.** + +**2.1. Patent License.** + +**2.1.1. As a Result of Contributions.** + +**2.1.1.1. As a Result of Contributions to Draft Specifications.** Contributor grants Licensee a non-sublicensable, perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as expressly stated in this License) license to its Necessary Claims in 1) Contributor’s Contributions and 2) to the Draft Specification that is within Scope as of the date of that Contribution, in both cases for Licensee’s Implementation of the Draft Specification, except for those patent claims excluded by Contributor under Section 3. + +**2.1.1.2. For Approved Specifications.** Contributor grants Licensee a non-sublicensable, perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as expressly stated in this License) license to its Necessary Claims included the Approved Specification that are within Scope for Licensee’s Implementation of the Approved Specification, except for those patent claims excluded by Contributor under Section 3. + +**2.1.2. Patent Grant from Licensee.** Licensee grants each other Licensee a non-sublicensable, perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as expressly stated in this License) license to its Necessary Claims for its Implementation, except for those patent claims excluded under Section 3. + +**2.1.3. Licensee Acceptance.** The patent grants set forth in Section 2.1 extend only to Licensees that have indicated their agreement to this License as follows: + +**2.1.3.1. Source Code Distributions.** For distribution in source code, by including this License in the root directory of the source code with the Implementation; + +**2.1.3.2. Non-Source Code Distributions.** For distribution in any form other than source code, by including this License in the documentation, legal notices, via notice in the software, and/or other written materials provided with the Implementation; or + +**2.1.3.3. Via Notices.md.** By issuing pull request or commit to the Specification’s repository’s Notices.md file by the Implementer’s authorized representative, including the Implementer’s name, authorized individual and system identifier, and Specification version. + +**2.1.4. Defensive Termination.** If any Licensee files or maintains a claim in a court asserting that a Necessary Claim is infringed by an Implementation, any licenses granted under this License to the Licensee are immediately terminated unless 1) that claim is directly in response to a claim against Licensee regarding an Implementation, or 2) that claim was brought to enforce the terms of this License, including intervention in a third-party action by a Licensee. + +**2.1.5. Additional Conditions.** This License is not an assurance (i) that any of Contributor’s copyrights or issued patent claims cover an Implementation of the Specification or are enforceable or (ii) that an Implementation of the Specification would not infringe intellectual property rights of any third party. + +**2.2. Patent Licensing Commitment.** In addition to the rights granted in Section 2.1, Contributor agrees to grant everyone a no charge, royalty-free license on reasonable and non-discriminatory terms to Contributor’s Necessary Claims that are within Scope for: +1) Implementations of a Draft Specification, where such license applies only to those Necessary Claims infringed by implementing Contributor's Contribution(s) included in that Draft Specification, and +2) Implementations of the Approved Specification. + +This patent licensing commitment does not apply to those claims subject to Contributor’s Exclusion Notice under Section 3. + +**2.3. Effect of Withdrawal.** Contributor may withdraw from the Working Group by issuing a pull request or commit providing notice of withdrawal to the Working Group repository’s Notices.md file. All of Contributor’s existing commitments and obligations with respect to the Working Group up to the date of that withdrawal notice will remain in effect, but no new obligations will be incurred. + +**2.4. Binding Encumbrance.** This License is binding on any future owner, assignee, or party who has been given the right to enforce any Necessary Claims against third parties. + +**3. Patent Exclusion.** + +**3.1. As a Result of Contributions.** Contributor may exclude Necessary Claims from its licensing commitments incurred under Section 2.1.1 by issuing an Exclusion Notice within 45 days of the date of that Contribution. Contributor may not issue an Exclusion Notice for any material that has been included in a Draft Deliverable for more than 45 days prior to the date of that Contribution. + +**3.2. As a Result of a Draft Specification Becoming an Approved Specification.** Prior to the adoption of a Draft Specification as an Approved Specification, Contributor may exclude Necessary Claims from its licensing commitments under this Agreement by issuing an Exclusion Notice. Contributor may not issue an Exclusion Notice for patents that were eligible to have been excluded pursuant to Section 3.1. + +**4. Source Code License.** Any source code developed by the Working Group is solely subject the source code license included in the Working Group’s repository for that code. If no source code license is included, the source code will be subject to the MIT License. + +**5. No Other Rights.** Except as specifically set forth in this License, no other express or implied patent, trademark, copyright, or other rights are granted under this License, including by implication, waiver, or estoppel. + +**6. Antitrust Compliance.** Contributor acknowledge that it may compete with other participants in various lines of business and that it is therefore imperative that they and their respective representatives act in a manner that does not violate any applicable antitrust laws and regulations. This License does not restrict any Contributor from engaging in similar specification development projects. Each Contributor may design, develop, manufacture, acquire or market competitive deliverables, products, and services, and conduct its business, in whatever way it chooses. No Contributor is obligated to announce or market any products or services. Without limiting the generality of the foregoing, the Contributors agree not to have any discussion relating to any product pricing, methods or channels of product distribution, division of markets, allocation of customers or any other topic that should not be discussed among competitors under the auspices of the Working Group. + +**7. Non-Circumvention.** Contributor agrees that it will not intentionally take or willfully assist any third party to take any action for the purpose of circumventing any obligations under this License. + +**8. Representations, Warranties and Disclaimers.** + +**8.1. Representations, Warranties and Disclaimers.** Contributor and Licensee represents and warrants that 1) it is legally entitled to grant the rights set forth in this License and 2) it will not intentionally include any third party materials in any Contribution unless those materials are available under terms that do not conflict with this License. IN ALL OTHER RESPECTS ITS CONTRIBUTIONS ARE PROVIDED "AS IS." The entire risk as to implementing or otherwise using the Contribution or the Specification is assumed by the implementer and user. Except as stated herein, CONTRIBUTOR AND LICENSEE EXPRESSLY DISCLAIM ANY WARRANTIES (EXPRESS, IMPLIED, OR OTHERWISE), INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, CONDITIONS OF QUALITY, OR TITLE, RELATED TO THE CONTRIBUTION OR THE SPECIFICATION. IN NO EVENT WILL ANY PARTY BE LIABLE TO ANY OTHER PARTY FOR LOST PROFITS OR ANY FORM OF INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER FROM ANY CAUSES OF ACTION OF ANY KIND WITH RESPECT TO THIS AGREEMENT, WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, AND WHETHER OR NOT THE OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Any obligations regarding the transfer, successors in interest, or assignment of Necessary Claims will be satisfied if Contributor or Licensee notifies the transferee or assignee of any patent that it knows contains Necessary Claims or necessary claims under this License. Nothing in this License requires Contributor to undertake a patent search. If Contributor is 1) employed by or acting on behalf of an employer, 2) is making a Contribution under the direction or control of a third party, or 3) is making the Contribution as a consultant, contractor, or under another similar relationship with a third party, Contributor represents that they have been authorized by that party to enter into this License on its behalf. + +**8.2. Distribution Disclaimer.** Any distributions of technical information to third parties must include a notice materially similar to the following: “THESE MATERIALS ARE PROVIDED “AS IS.” The Contributors and Licensees expressly disclaim any warranties (express, implied, or otherwise), including implied warranties of merchantability, non-infringement, fitness for a particular purpose, or title, related to the materials. The entire risk as to implementing or otherwise using the materials is assumed by the implementer and user. IN NO EVENT WILL THE CONTRIBUTORS OR LICENSEES BE LIABLE TO ANY OTHER PARTY FOR LOST PROFITS OR ANY FORM OF INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER FROM ANY CAUSES OF ACTION OF ANY KIND WITH RESPECT TO THIS DELIVERABLE OR ITS GOVERNING AGREEMENT, WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, AND WHETHER OR NOT THE OTHER MEMBER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.” + +**9. Definitions.** + +**9.1. Affiliate.** “Affiliate” means an entity that directly or indirectly Controls, is Controlled by, or is under common Control of that party. + +**9.2. Approved Specification.** “Approved Specification” means the final version and contents of any Draft Specification designated as an Approved Specification as set forth in the accompanying Governance.md file. + +**9.3. Contribution.** “Contribution” means any original work of authorship, including any modifications or additions to an existing work, that Contributor submits for inclusion in a Draft Specification, which is included in a Draft Specification or Approved Specification. + +**9.4. Contributor.** “Contributor” means any person or entity that has indicated its acceptance of the License 1) by making a Contribution to the Specification, or 2) by entering into the Community Specification Contributor License Agreement for the Specification. Contributor includes its Affiliates, assigns, agents, and successors in interest. + +**9.5. Control.** “Control” means direct or indirect control of more than 50% of the voting power to elect directors of that corporation, or for any other entity, the power to direct management of such entity. + +**9.6. Draft Specification.** “Draft Specification” means all versions of the material (except an Approved Specification) developed by this Working Group for the purpose of creating, commenting on, revising, updating, modifying, or adding to any document that is to be considered for inclusion in the Approved Specification. + +**9.7. Exclusion Notice.** “Exclusion Notice” means a written notice made by making a pull request or commit to the repository’s Notices.md file that identifies patents that Contributor is excluding from its patent licensing commitments under this License. The Exclusion Notice for issued patents and published applications must include the Draft Specification’s name, patent number(s) or title and application number(s), as the case may be, for each of the issued patent(s) or pending patent application(s) that the Contributor is excluding from the royalty-free licensing commitment set forth in this License. If an issued patent or pending patent application that may contain Necessary Claims is not set forth in the Exclusion Notice, those Necessary Claims shall continue to be subject to the licensing commitments under this License. The Exclusion Notice for unpublished patent applications must provide either: (i) the text of the filed application; or (ii) identification of the specific part(s) of the Draft Specification whose implementation makes the excluded claim a Necessary Claim. If (ii) is chosen, the effect of the exclusion will be limited to the identified part(s) of the Draft Specification. + +**9.8. Implementation.** “Implementation” means making, using, selling, offering for sale, importing or distributing any implementation of the Specification 1) only to the extent it implements the Specification and 2) so long as all required portions of the Specification are implemented. + +**9.9. License.** “License” means this Community Specification License. + +**9.10. Licensee.** “Licensee” means any person or entity that has indicated its acceptance of the License as set forth in Section 2.1.3. Licensee includes its Affiliates, assigns, agents, and successors in interest. + +**9.11. Necessary Claims.** “Necessary Claims” are those patent claims, if any, that a party owns or controls, including those claims later acquired, that are necessary to implement the required portions (including the required elements of optional portions) of the Specification that are described in detail and not merely referenced in the Specification. + +**9.12. Specification.** “Specification” means a Draft Specification or Approved Specification included in the Working Group’s repository subject to this License, and the version of the Specification implemented by the Licensee. + +**9.13. Scope.** “Scope” has the meaning as set forth in the accompanying Scope.md file included in this Specification’s repository. Changes to Scope do not apply retroactively. If no Scope is provided, each Contributor’s Necessary Claims are limited to that Contributor’s Contributions. + +**9.14. Working Group.** “Working Group” means this project to develop specifications, standards, best practices, guidelines, and other similar materials under this License. + + + +*The text of this Community Specification License is Copyright 2020 Joint Development Foundation and is licensed under the Creative Commons Attribution 4.0 International License available at https://creativecommons.org/licenses/by/4.0/.* + +SPDX-License-Identifier: CC-BY-4.0 diff --git a/Governance.md b/Governance.md new file mode 100644 index 0000000..b36de21 --- /dev/null +++ b/Governance.md @@ -0,0 +1,51 @@ +# Community Specification Governance Policy 1.0 + +This document provides the governance policy for specifications and other documents developed using the Community Specification process in a repository (each a “Working Group”). Each Working Group and must adhere to the requirements in this document. + +## 1. Roles. + +Each Working Group may include the following roles. Additional roles may be adopted and documented by the Working Group. + +**1.1. Maintainer.** “Maintainers” are responsible for organizing activities around developing, maintaining, and updating the specification(s) developed by the Working Group. Maintainers are also responsible for determining consensus and coordinating appeals. Each Working Group will designate one or more Maintainer for that Working Group. A Working Group may select a new or additional Maintainer(s) upon Approval of the Working Group Participants. + +**1.2. Editor.** “Editors” are responsible for ensuring that the contents of the document accurately reflect the decisions that have been made by the group, and that the specification adheres to formatting and content guidelines. Each Working Group will designate an Editor for that Working Group. A Working Group may select a new Editor upon Approval of the Working Group Participants. + +**1.3. Participants.** “Participants” are those that have made Contributions to the Working Group subject to the Community Specification License. + +## 2. Decision Making. + +**2.1. Consensus-Based Decision Making.** Working Groups make decisions through a consensus process (“Approval” or “Approved”). While the agreement of all Participants is preferred, it is not required for consensus. Rather, the Maintainer will determine consensus based on their good faith consideration of a number of factors, including the dominant view of the Working Group Participants and nature of support and objections. The Maintainer will document evidence of consensus in accordance with these requirements. + +**2.2. Appeal Process.** Decisions may be appealed be via a pull request or an issue, and that appeal will be considered by the Maintainer in good faith, who will respond in writing within a reasonable time. + +## 3. Ways of Working. + +Inspired by [ANSI’s Essential Requirements for Due Process](https://share.ansi.org/Shared%20Documents/Standards%20Activities/American%20National%20Standards/Procedures,%20Guides,%20and%20Forms/2020_ANSI_Essential_Requirements.pdf), Community Specification Working Groups must adhere to consensus-based due process requirements. These requirements apply to activities related to the development of consensus for approval, revision, reaffirmation, and withdrawal of Community Specifications. Due process means that any person (organization, company, government agency, individual, etc.) with a direct and material interest has a right to participate by: a) expressing a position and its basis, b) having that position considered, and c) having the right to appeal. Due process allows for equity and fair play. The following constitute the minimum acceptable due process requirements for the development of consensus. + +**3.1. Openness.** Participation shall be open to all persons who are directly and materially affected by the activity in question. There shall be no undue financial barriers to participation. Voting membership on the consensus body shall not be conditional upon membership in any organization, nor unreasonably restricted on the basis of technical qualifications or other such requirements. Membership in a Working Group’s parent organization, if any, may be required. + +**3.2. Lack of Dominance.** The development process shall not be dominated by any single interest category, individual or organization. Dominance means a position or exercise of dominant authority, leadership, or influence by reason of superior leverage, strength, or representation to the exclusion of fair and equitable consideration of other viewpoints. + +**3.3. Balance.** The development process should have a balance of interests. Participants from diverse interest categories shall be sought with the objective of achieving balance. + +**3.4. Coordination and Harmonization.** Good faith efforts shall be made to resolve potential conflicts between and among deliverables developed under this Working Group and existing industry standards. + +**3.5. Consideration of Views and Objections.** Prompt consideration shall be given to the written views and objections of all Participants. + +**3.6. Written procedures.** This governance document and other materials documenting the Community Specification development process shall be available to any interested person. + +## 4. Specification Development Process. + +**4.1. Pre-Draft.** Any Participant may submit a proposed initial draft document as a candidate Draft Specification of that Working Group. The Maintainer will designate each submission as a “Pre-Draft” document. + +**4.2. Draft.** Each Pre-Draft document of a Working Group must first be Approved to become a” Draft Specification”. Once the Working Group approves a document as a Draft Specification, the Draft Specification becomes the basis for all going forward work on that specification. + +**4.3. Working Group Approval.** Once a Working Group believes it has achieved the objectives for its specification as described in the Scope, it will Approve that Draft Specification and progress it to “Approved Specification” status. + +**4.4. Publication and Submission.** Upon the designation of a Draft Specification as an Approved Specification, the Maintainer will publish the Approved Specification in a manner agreed upon by the Working Group Participants (i.e., Working Group Participant only location, publicly available location, Working Group maintained website, Working Group member website, etc.). The publication of an Approved Specification in a publicly accessible manner must include the terms under which the Approved Specification is being made available under. + +**4.5. Submissions to Standards Bodies.** No Draft Specification or Approved Specification may be submitted to another standards development organization without Working group Approval. Upon reaching Approval, the Maintainer will coordinate the submission of the applicable Draft Specification or Approved Specification to another standards development organization. Working Group Participants that developed that Draft Specification or Approved Specification agree to grant the copyright rights necessary to make those submissions. + +## 5. Non-Confidential, Restricted Disclosure. + +Information disclosed in connection with any Working Group activity, including but not limited to meetings, Contributions, and submissions, is not confidential, regardless of any markings or statements to the contrary. Notwithstanding the foregoing, if the Working Group is collaborating via a private repository, the Participants will not make any public disclosures of that information contained in that private repository without the Approval of the Working Group. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c7d1e9f --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +# Licenses + +## Specification License + +Specifications in the repository are subject to the **Community Specification License 1.0** available at [https://github.com/CommunitySpecification/1.0](https://github.com/CommunitySpecification/1.0). + +## Source Code License + +If source code is included in this repository, or for sample or reference code included in the specification itself, that code is subject to the MIT license unless otherwise designated. In the case of any conflict or confusion within this specification repository between the Community Specification License and the MIT or other designated license, the terms of the Community Specification License shall apply. + +If source code is included in this repository, or for sample or reference code included in the specification itself, that code is subject to the MIT license unless otherwise marked. + +In the case of any conflict or confusion within this specification repository between the Community Specification License and the designated source code license, the terms of the Community Specification License shall apply. diff --git a/Notices.md b/Notices.md new file mode 100644 index 0000000..28a77da --- /dev/null +++ b/Notices.md @@ -0,0 +1,138 @@ +# Notices + +## Code of Conduct + +The Code of Conduct is available in the repository in [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md). + +Contact for Code of Conduct issues or inquires: hello@brooklynzelenka.com, hello@fission.codes + +## License Acceptance + +Per Community Specification License 1.0 Section 2.1.3.3, Licensees may indicate their acceptance of the Community Specification License by issuing a pull request to the Specification’s repository’s Notice.md file, including the Licensee’s name, authorized individuals' names, and repository system identifier (e.g. GitHub ID), and specification version. + +A Licensee may consent to accepting the current Community Specification License version or any future version of the Community Specification License by indicating "or later" after their specification version. + +--------------------------------------------------------------------------------- + +Licensee’s name: Brooklyn Zelenka + +Authorized individual and system identifier: expede + +Specification version: 0.8.0 or later + +--------------------------------------------------------------------------------- + +Licensee’s name: Brian Ginsburg + +Authorized individual and system identifier: bgins + +Specification version: 0.8.0 or later + +--------------------------------------------------------------------------------- + +Licensee’s name: Stephen Akinyemi + +Authorized individual and system identifier: appcypher + +Specification version: 0.8.0 or later + +--------------------------------------------------------------------------------- + +Licensee’s name: Quinn Wilton + +Authorized individual and system identifier: QuinnWilton + +Specification version: 0.8.0 or later + +--------------------------------------------------------------------------------- + +Licensee’s name: Philipp Krüger + +Authorized individual and system identifier: matheus23 + +Specification version: 0.8.0 or later + +--------------------------------------------------------------------------------- + + +Licensee’s name: Boris Mann + +Authorized individual and system identifier: bmann + +Specification version: 0.8.0 or later + +--------------------------------------------------------------------------------- + +Licensee’s name: Daniel Holmgren + +Authorized individual and system identifier: dholms + +Specification version: 0.8.0 or later + +--------------------------------------------------------------------------------- + +Licensee’s name: Irakli Gozalishvili + +Authorized individual and system identifier: gozala + +Specification version: 0.8.0 or later + +--------------------------------------------------------------------------------- + +Licensee’s name: Brendan O'Brien + +Authorized individual and system identifier: b5 + +Specification version: 0.8.0 or later + +--------------------------------------------------------------------------------- + +Licensee’s name: Benjamin Goering + +Authorized individual and system identifier: gobengo + +Specification version: 0.8.0 or later + +--------------------------------------------------------------------------------- + +Licensee’s name: Nicolas Gimenez + +Authorized individual and system identifier: nicobao + +Specification version: 0.8.0 or later + +--------------------------------------------------------------------------------- + +## Withdrawals + +Name of party withdrawing: + +Date of withdrawal: + +--------------------------------------------------------------------------------- + +## Exclusions + +This section includes any Exclusion Notices made against a Draft Deliverable or Approved Deliverable as set forth in the Community Specification Development License. Each Exclusion Notice must include the following information: + +- Name of party making the Exclusion Notice: + +- Name of patent owner: + +- Specification: + +- Version number: + +**For issued patents and published patent applications:** + + (i) patent number(s) or title and application number(s), as the case may be: + + (ii) identification of the specific part(s) of the Specification whose implementation makes the excluded claim a Necessary Claim. + +**For unpublished patent applications must provide either:** + + (i) the text of the filed application; or + + (ii) identification of the specific part(s) of the Specification whose implementation makes the excluded claim a Necessary Claim. + +----------------------------------------------------------------------------------------- diff --git a/README.md b/README.md index e69de29..99d839d 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,954 @@ +# UCAN Delegation Specification +## Version 1.0.0-rc.1 + +## Editors +[Editors]: #editors + +- [Brooklyn Zelenka], [Witchcraft Software] + +## Authors +[Authors]: #authors + +- [Brooklyn Zelenka], [Witchcraft Software] +- [Daniel Holmgren], [Bluesky] +- [Irakli Gozalishvili], [Common Tools] +- [Philipp Krüger], [number zero] + +## Dependencies +[Dependencies]: #dependencies + +- [UCAN] + +## Language +[Language]: #language + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP 14] when, and only when, they appear in all capitals, as shown here. + +# Abstract +[Abstract]: #abstract + +This specification describes the representation and semantics for delegating attenuated authority between principals. UCAN Delegation provides a cryptographically verifiable container, batched capabilities, hierarchical authority, and a minimal syntatically-driven policy langauge. + +# Introduction +[Introduction]: #introduction + +UCAN Delegation is a delegable certificate capability system with runtime-extensibility, ad hoc conditions, cacheability, and focused on ease of use and interoperability. Delegations act as a proofs for [UCAN Invocation]s. + +Delegation provides a way to "transfer authority without transferring cryptographic keys". As an authorization system, it is more interested in "what can be done" than a list of "who can do what". For more on how Delegation fits into UCAN, please refer to the [high level spec][UCAN]. + +# [UCAN Envelope] Configuration +[UCAN Envelope Configuration]: #ucan-envelope-configuration + +## Type Tag +[Type Tag]: #type-tag + +The UCAN envelope tag for UCAN Delegation MUST be set to `ucan/dlg@1.0.0-rc.1`. + +## Delegation Payload +[Delegation Payload]: #delegation-payload + +The Delegation payload MUST describe the authorization claims, who is involved, and its validity period. + +| Field | Type | Required | Description | +|---------|-------------------------------------------|----------|---------------------------------------------------------------------------| +| `iss` | `DID` | Yes | Issuer DID (sender). All [DID][did-spec]s are represented as string URLs. | +| `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 | +| `pol` | `Policy` | Yes | [Policy] | +| `nonce` | `Bytes` | Yes | Nonce | +| `meta` | `{String : Any}` | No | [Meta] (asserted, signed data) — is not delegated authority | +| `nbf` | `Integer` (53-bits[^js-num-size]) | No | "Not before" UTC Unix Timestamp in seconds (valid from) | +| `exp` | `Integer \| null` (53-bits[^js-num-size]) | Yes | Expiration UTC Unix Timestamp in seconds (valid until) | + +[^js-num-size]: JavaScript has a single numeric type ([`Number`][JS Number]) for both integers and floats. This representation is defined as a [IEEE-754] double-precision floating point number, which has a 53-bit significand. + +# Capability +[Capability]: #capability + +A capability is the semantically-relevant claim of a delegation. They MUST take the following form: + +| Field | Type | Required | Description | +|--------|---------------|----------|----------------------------------------------------------------------------------------------------------| +| `sub` | `DID \| null` | Yes | The [Subject] that this Capability is about | +| `cmd` | `Command` | Yes | The [Command] of this Capability | +| `pol` | `Policy` | Yes | Additional constraints on eventual Invocation arguments, expressed in the [UCAN Policy Language][Policy] | + +Here is an illustrative example: + +``` js +{ + // ... + "sub": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp" + "cmd": "/blog/post/create", + "pol": [ + ["==", ".status", "draft"], + ["all", ".reviewer", ["like", ".email", "*@example.com"]], + ["any", ".tags", + ["or", + ["==", ".", "news"], + ["==", ".", "press"]]] + ] +} +``` + +## Subject +[Subject]: #subject + +The Subject MUST be the DID that initiated the delegation chain, or an explicit `null`. Declaring a DID is RECOMMENDED. For more on the `null`, please see the [Powerline] section. + +``` js +{ + "sub": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp", + // ... +} +``` + +### Resource +[Resource]: #resource + +Unlike [Subjects][Subject] and [Commands][Command], Resources are _semantic_ rather than syntactic. The Resource is the "what" that a capability describes. + +By default, the Resource of a capability is the Subject. This makes the delegation chain self-certifying. + +``` js +{ + "sub": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp", // Subject + // ... +} +``` + +In the case where access to an [external resource] is delegated, the Subject MUST own the relationship to the Resource. The Resource SHOULD be referenced by a `uri` key in the relevant [Conditions], except where it would be clearer to do otherwise. This MUST be defined by the Subject and understood by the executor. + +``` js +{ + "sub": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp", + "cmd": "/crud/create", + "pol": [ + ["==", ".url", "https://example.com/blog/"], // Resource managed by the Subject + // ... + ], + // ... +} +``` + +### Powerline +[Powerline]: #powerline + +> [!WARNING] +> Similar to `cmd: "/"` and `pol: []`, this feature (`sub: null`) is very powerful. Use with care. + +A "Powerline"[^powerbox] is a pattern for automatically delegating _all_ future delegations to another agent regardless of [Subject]. This is achieved by explicitly setting the [Subject] (`sub`) field to `null`. At [Validation] time, the [Subject] MUST be substituted for the directly prior Subject given in the delegation chain. All other fields MUST continue to validate as normal (e.g. [principal alignment][Principal Alignment], [time bounds][Time Bounds], and so on). + +[^powerbox]: For those familiar with design patterns for object capabilities, a "Powerline" is like a [Powerbox] but adapted for the partition-tolerant, static token context of UCAN. + +Powerline delegations MUST NOT be used as the root delegation to a resource. A priori there is no such thing as a `null` subject a prior. + +A very common use case for Powerlines is providing a stable DID across multiple agents (e.g. representing a user with multiple devices). This enables the automatic sharing of authority across their devices without needing to share keys or set up a threshold scheme. It is also flexible, since a Powerline delegation MAY be [revoked][revocation]. + +``` mermaid +sequenceDiagram + autonumber + + participant Email Server + participant Alice Root + participant Alice's Phone + participant Alice's Tablet + participant Alice's Laptop + + Alice Root ->> Alice's Phone: Delegate {sub: null, cmd: "/"} + Alice Root ->> Alice's Tablet: Delegate {sub: null, cmd: "/"} + Alice Root ->> Alice's Laptop: Delegate {sub: null, cmd: "/"} + + Email Server ->> Alice Root: Delegate {sub: "did:example:email", cmd: "/msg/send"} + + Alice's Tablet -->> Email Server: INVOKE! {sub: "did:example:email", cmd: "/msg/send", proofs: [❹,❷]} +``` + +Powerlines MAY include other restrictions, such as [time bounds][Time Bounds], [Commands][Command], and [Policies][Policy]. For example, the ability to automatically redelegate read-only access to arbitrary CRUD resources could be expressed as: + +``` js +{ + "iss": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp", + "aud": "did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme", + "sub": null, // 👈 ⚡ Powerline + "cmd": "/crud/read", + "pol": [], + // ... +} +``` + +## Command +[Command]: #command + +The [Command][High Level Command] MUST be a `/` delimited path describing set of commands delegated. +Delegation covers exact [Command] specified and all the commands described by a paths nested under that specified command. + +> [!NOTE] +> The command path syntax is designed to support forward compatible protocol extensions. Backwards-compatibl️️️️️️️️️️e capabilities MAY be introduced as command subpaths. + +> [!WARNING] +> By definition `"/"` implies all of the commands available on a resource, and SHOULD be used with great care. + +# Policy +[Policy]: #policy + +UCAN Delegation uses predicate logic statements extended with [jq]-inspired selectors as a policy language. Policies are syntactically driven, and MUST constrain the `args` field of an eventual [Invocation]. + +A Policy is always given as an array of predicates. This top-level array is implicitly treated as a logical `and`, where `args` MUST pass validation of every top-level predicate. + +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]`. + +``` ipldsch +-- Statements + +type Statement union { + | Equality + | Inequality + | Connective + | Negation + | Quantifier +} + +-- Equality + +type EqOp enum { + | Eq ("==") + | Neq ("!=") +} + +type Equality struct { + op EqOp + sel Selector + val Any +} representation tuple + +type LikeOp enum { + | Like ("like") +} + +type Like struct { + op LikeOp + sel Selector + str Wildcard +} representation tuple + +-- Inequality + +type IneqOp enum { + | GT (">") + | GTE (">=") + | LT ("<") + | LTE ("<=") +} + +type Inequality struct { + op IneqOp + sel Selector + val Number +} representation tuple + +-- Connectives + +type NegateOp { + | Not ("not") +} + +type Negation struct { + op NegateOp + smts [Statement] +} representation tuple + +type ConnectiveOp enum { + | And ("and") + | Or ("or") +} + +type Connective struct { + op ConnectiveOp + smts [Statement] +} representation tuple + +-- Quantification + +type QuantifierOp enum { + | All ("all") + | Any ("any") +} + +type Quantifier struct { + op QuantiefierOp + sel Selector + smt Statement +} representation tuple + +-- Primitives + +type Selector = string + +type Number union { + | NumInt int + | NumFloat float +} representation kinded + +type Wildcard = string +``` + +## Comparisons +[Comparisons]: #comparisons + +| Operator | Argument(s) | Example | +|----------|--------------------------------|----------------------------------| +| `==` | `Selector, IPLD` | `["==", ".a", [1, 2, {"b": 3}]]` | +| `<` | `Selector, (integer \| float)` | `["<", ".a", 1]` | +| `<=` | `Selector, (integer \| float)` | `["<=", ".a", 1]` | +| `>` | `Selector, (integer \| float)` | `[">", ".a", 1]` | +| `>=` | `Selector, (integer \| float)` | `[">=", ".a", 1]` | + +Literal equality (`==`) MUST match the resolved selecor to entire IPLD argument. This is a "deep comparison". + +Numeric inequalities MUST be agnostic to numeric type. In other words, the decimal representation is considered equivalent to an integer (`1 == 1.0 == 1.00`). Attempting to compare a non-numeric type MUST return false and MUST NOT throw an exception. + +## Glob Matching +[Glob Matching]: #glob-matching + +| Operator | Argument(s) | Example | +|----------|---------------------|---------------------------------------| +| `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. + +The wildcard represents zero-or-more characters. The following string literals MUST pass validation for the pattern `"Alice\*, Bob*, Carol.`: + +* `"Alice*, Bob, Carol."` +* `"Alice*, Bob, Dan, Erin, Carol."` +* `"Alice*, Bob , Carol."` +* `"Alice*, Bob*, Carol."` + +The following MUST NOT pass validation for that same pattern: + +* `"Alice*, Bob, Carol"` (missing the final `.`) +* `"Alice*, Bob*, Carol!"` (final `.` MUST NOT be treated as a wildcard) +* `"Alice, Bob, Carol."` (missing the `*` after `Alice`) +* `"Alice Cooper, Bob, Carol."` (the `*` after `Alice` is an escaped literal in the pattern) +* `" Alice*, Bob, Carol. "` (whitespace in the pattern is significant) + +## Connectives +[Connectives]: #connectives + +Connectives add context to their enclosed statement(s). + +| Operator | Argument(s) | Example | +|----------|---------------|--------------------------------------------| +| `and` | `[Statement]` | `["and", [[">", ".a", 1], [">", ".b", 2]]` | +| `or` | `[Statement]` | `["or", [[">", ".a", 1], [">", ".b", 2]]` | +| `not` | `Statement` | `["not", [">", ".a", 1]]` | + +### And +[And]: #and + +`and` MUST take an arbitrarily long array of statements, and require that every inner statement be true. An empty array MUST be treated as true. + +```js +// Data +{ name: "Katie", age: 35, nationalities: ["Canadian", "South African"] } + +["and", []] +// ⬆️ true + +["and", [ + ["==", ".name", "Katie"], + [">=", ".age", 21] +]] +// ⬆️ true + +["and", [ + ["==", ".name", "Katie"], + [">=", ".age", 21], + ["==", ".nationalities", ["American"]] // ️⬅️ false +]] +// ⬆️ false +``` + +### Or +[Or]: #or + +`or` MUST take an arbitrarily long array of statements, and require that at least one inner statement be true. An empty array MUST be treated as true. + +```js +// Data +{ name: "Katie", age: 35, nationalities: ["Canadian", "South African"] } + +["or", []] +// ⬆️ true + +["or", [ + ["==", ".name", "Katie"], // ⬅️ true + [">", ".age", 45] +]] +// ⬆️ true +``` + +### Not +[Not]: #not + +`not` MUST invert the truth value of the inner statement. For example, if `["==", ".a", 1]` were false (`.a` is not 1), then `["not", ["==", ".a", 1]]` would be true. + +```js +// Data +{ name: "Katie", nationalities: ["Canadian", "South African"] } + +["not", + ["and", [ + ["==", ".name", "Katie"], + ["==", ".nationalities", ["American"]] // ⬅️ false +]] +// ⬆️ true +``` + +## Quantification +[Quantification]: #quantification + +When a selector resolves to a collection (an array or map), quantifiers provide a way to extend `and` and `or` to their contents. Attempting to quantify over a non-collection MUST return false and MUST NOT throw an exception. + +Quantifying over an array is straightforward: it MUST apply the inner statement to each array value. Quantifying over a map MUST extract the values (discarding the keys), and then MUST proceed onthe values the same as if it were an array. + +| Operator | Argument(s) | Example | +|----------|-------------------------|---------------------------------| +| `all` | `Selector, [Statement]` | `["all", ".a" [">", ".b", 1]]` | +| `any` | `Selector, [Statement]` | `["any", ".a" [">", ".b", 1]]` | + +`all` extends `and` over collections. `any` extends `or` over collections. For example: + +``` js +const args = {"a": [{"b": 1}, {"b": 2}, {"z": [7, 8, 9]}]} +const statement = ["all", ".a", [">", ".b", 0]] + +// Outer Selector Substitution +["all", [{"b": 1}, {"b": 2}, {"z": [7, 8, 9]}], [">", ".b", 0]] + +// Predicate Reduction +["and", [ + [">", 1, 0], + [">", 2, 0], + [">", null, 0] +]] + +["and", [ + true, + true, + false // ⬅️ +]] + +false // ❌ +``` + +``` js +const args = {"a": [{"b": 1}, {"b": 2}, {"z": [7, 8, 9]}]} +const statement = ["any", ".a", ["==", ".b", 2]] + +// Reduction +["any", [{"b": 1}, {"b": 2}, {"z": [7, 8, 9]}], ["==", ".b", 2]] + +["or", [ + ["==", 1, 2], + ["==", 2, 2], + ["==", null, 2] +]] + +["or", [ + false, + true, // ⬅️ + false +]] + +true // ✅ +``` + +### Nested Quantification +[Nested Quantification]: #nested-quantification + +Quantified statements MAY be nested. For example, the below states that someone with the email `fraud@example.com` is required to be among the receipts of every newsletter. + +``` js +["all", ".newsletters", + ["any", ".recipients", + ["==", ".email", "fraud@example.com"]]] +``` + +## Selectors +[Selectors]: #selectors + +Selector syntax is closely based on [jq]'s "filters". They operate on an [Invocation]'s `args` object. + +Selectors MUST only include the following features: + +| Selector Name | Examples | Notes | +|------------------------|-------------------------------------|------------------------------------------------------------------------------------------------------------------------| +| 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 | `["."]`, `["$_*"], ["1"]` | Select in a map by arbitrary key | +| Collection values | `[]` | Expands out all of the children that match the remaining path. On lists this is a noop. On maps, this extracts values. | +| List index | `[0]`, `[42]` | The list element of a list by 0-index. | +| Negative list index | `[-1]`, `[-42]` | The list element by index from the end. `-1` is the index for the last element. | +| List slices | `[7:11]`, `[2:]`, `[:42]`, `[0:-2]` | The range of elements by their indices. | +| Optional | `.foo?`, `["nope"]?` | Returns `null` on what would otherwise fail | + +Every selection MUST begin and/or end with a single dot. Multiple dots (e.g. `..`, `...`) MUST NOT be used anywhere in a selector. + +The optional operator is idempotent, and repeated optionals (`.foo???`) MUST be treated as a single one. + +For example, consider the following `args` from an `Invocation`: + +``` json +{ + "args": { + "from": "alice@example.com", + "to": ["bob@example.com", "carol@not.example.com", "dan@example.com"], + "cc": ["fraud@example.com"], + "title": "Meeting Confirmation", + "body": "I'll see you on Tuesday" + } +} +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SelectorReturned Value
"."
+ +```json +{ + "from": "alice@example.com", + "to": ["bob@example.com", "carol@not.example.com", "dan@example.com"], + "cc": ["fraud@example.com"], + "title": "Meeting Confirmation", + "body": "I'll see you on Tuesday" +} +``` + +
".title"
+ +``` json +"Meeting Confirmation" +``` + +
".cc"
+ +``` json +["fraud@example.com"] +``` + +
".to[1]"
+ +``` json +"carol@not.example.com" +``` + +
".to[-1]"
+ +``` json +"dan@example.com" +``` + +
".to[99]?"
+ +``` json +null +``` + +
+ +### Selecting on Bytes + +Bytes MAY be selected into. When doing so, they MUST be treated as a byte array (`[u8]`), and MUST NOT be treated as a Base64 string or any other representation. + +``` js +// DAG-JSON +{ "/": { "bytes": "1qnBjPjE" } } + +// Hexadecimal +0xd6 0xa9 0xc1 0x8c 0xf8 0xc4 + +// Selector +".[3]" +// ⬆️ 0x8c = 140 +``` + +### Differences from jq +[Differences from jq]: #differences-from-jq + +[jq] is a much larger language than UCAN's selectors. jq includes features like pipes, arithmatic, regexes, assignment, recursive descent, and so on which are not supported in the UCAN Policy language, and thus MUST NOT be implemented in UCAN. + +jq produces streams of values (a distrinct concept from arrays), in contrast to UCAN argument selectors which always return an IPLD value. This introduces the primary difference between jq and UCAN argument selectors is how to treat output of the optional (`?`) operator: UCAN's optional selector operator MUST return `null` for the failure case. + +There are FIXME + +## Validation +[Validation]: #validation + +Validation involves substituting the values from the `args` field into the Policy, and evaluating the predicate. Since Policies are tree structured, selector substitution and predicate evaluation MAY proceed in any order. + +If a selector cannot be resolved (there is no value at that path), the associated statement MUST return false, and MUST NOT throw an exception. Note that for consistent semantics, selecting a missing keys on a map MUST return `null` (but nested selectors without an optional MUST then fail the predicate). + +Below is a step-by-step evaluation example: + +``` js +{ // Invocation + "cmd": "/msg/send", + "args": { + "from": "alice@example.com", + "to": ["bob@example.com", "carol@not.example.com"], + "title": "Coffee", + "body": "Still on for coffee" + }, + // ... +} + +{ // Delegation + "cmd": "/msg", + "pol": [ + ["==", ".from", "alice@example.com"], + ["any", ".to", ["like", ".", "*@example.com"]] + ], + // ... +} +``` + +``` js +[ // Extract policy + ["==", ".from", "alice@example.com"], + ["any", ".to", ["like", ".", "*@example.com"]] +] + +[ // Resolve selectors + ["==", "alice@example.com", "alice@example.com"], + ["any", ["bob@example.com", "carol@elsewhere.example.com"], ["like", ".", "*@example.com"]] +] + +[ // Expand quantifier + ["==", "alice@example.com", "alice@example.com"], + ["or", [ + ["like", "bob@example.com", "*@example.com"] + ["like", "carol@elsewhere.example.com", "*@example.com"]] + ] +] + +[ // Evaluate first predicate + true, + ["or", [ + ["like", "bob@example.com", "*@example.com"] + ["like", "carol@elsewhere.example.com", "*@example.com"]]] +] + +[ // Evaluate second predicate's children + true, + ["or", [true, false]] +] + + +[ // Evaluate second predicate + true, + true +] + +// Evaluate top-level `and` +true +``` + +Any arguments MUST be taken verbatim and MUST NOT be further adjusted. For more flexible validation of Arguments, use [Conditions]. + +Note that this also applies to arrays and objects. For example, the `to` array in this example is considered to be exact, so the Invocation fails validation in this case: + +``` js +// Delegation +{ + "cmd": "/email/send", + "pol": [ + ["==", ".from", "alice@example.com"], + ["any", ".to", ["like", ".", "*@example.com"]] + ] + // ... +} + +// VALID Invocation +{ + "cmd": "/email/send", + "args": { + "from": "alice@example.com", + "to": ["bob@example.com", "carol@elsewhere.example.com"], + "title": "Coffee", + "body": "Still on for coffee" + }, + // ... +} + +// INVALID Invocation +{ + "cmd": "/email/send", + "args": { + "from": "alice@example.com", + "to": ["carol@elsewhere.example.com"], // No match for `*@example.com` + "title": "Coffee", + "body": "Still on for coffee" + }, + // ... +} +``` + +## Semantic Conditions +[Semantics Conditions]: #semantic-conditions + +Other semantic conditions that are not possible to fully express syntactically (e.g. current day of week) MUST be handled as part of Invocation execution. This is considered out of scope of the UCAN Policy language. The RECOMMENDED strategy to express constrains that involve side effects (like day of week) is to include that infromation in the argument shape for that Command (i.e. have a `"day_of_week": "friday"` field). + +# Token Validation +[Token Validation]: #token-validation + +Validation of a UCAN chain MAY occur at any time, but MUST occur upon receipt of an [Invocation] _prior to execution_. While proof chains exist outside of a particular delegation (and are made concrete in [UCAN Invocation]s), each delegate MUST store one or more valid delegations chains for a particular claim. + +Each capability has its own semantics, which needs to be interpretable by the [Executor]. Therefore, a validator MUST NOT reject all capabilities when one that is not relevant to them is not understood. For example, if a Condition fails a delegation check at execution time, but is not relevant to the invocation, it MUST be ignored. + +If _any_ of the following criteria are not met, the UCAN Delegation MUST be considered invalid: + +1. [Time Bounds] +2. [Principal Alignment] +3. [Signature Validation] + +Additional constraints MAY be placed on Delegations by specs that use them (notably [UCAN Invocation]). + +## Time Bounds +[Time Bounds]: #time-bounds + +A UCAN's time bounds MUST NOT be considered valid if the current system time is before the `nbf` field or after the `exp` field. This is called the "validity period." Proofs in a chain MAY have different validity periods, but MUST all be valid at execution-time. This has the effect of making a delegation chain valid between the latest `nbf` and earliest `exp`. + +``` js +// Pseudocode + +const ensureTime = (delegationChain, now) => { + delegationChain.forEach((ucan) => { + if (!!ucan.nbf && now < can.nbf) { + throw new Error(`Delegation is not yet valid, but will become valid at ${ucan.nbf}`) + } + + if (ucan.exp !== null && now > ucan.exp) { + throw new Error(`Delegation expired at ${ucan.exp}`) + } + }) +} +``` + +## Principal Alignment +[Principal Alignment]: #principal-alignment + +In delegation, the `aud` field of every proof MUST match the `iss` field of the UCAN being delegated to. This alignment MUST form a chain back to the Subject for each resource. + +This calculation MUST NOT take into account [DID fragment]s. If present, fragments are only intended to clarify which of a DID's keys was used to sign a particular UCAN, not to limit which specific key is delegated between. Use `did:key` if delegation to a specific key is desired. + +``` mermaid +flowchart RL + invoker((    Dan    )) + subject((    Alice    )) + + subject -- controls --> resource[(Storage)] + rootCap -- references --> resource + + subgraph Delegations + subgraph root [Root UCAN] + subgraph rooting [Root Issuer] + rootIss(iss: Alice) + rootSub(sub: Alice) + end + + rootCap("cap: (Storage, crud/*)") + rootAud(aud: Bob) + end + + subgraph del1 [Delegated UCAN] + del1Iss(iss: Bob) --> rootAud + del1Sub(sub: Alice) + del1Aud(aud: Carol) + del1Cap("cap: (Storage, crud/*)") --> rootCap + + + del1Sub --> rootSub + end + + subgraph del2 [Delegated UCAN] + del2Iss(iss: Carol) --> del1Aud + del2Sub(sub: Alice) + del2Aud(aud: Dan) + del2Cap("cap: (Storage, crud/*)") --> del1Cap + + del2Sub --> del1Sub + end + end + + subgraph inv [Invocation] + invIss(iss: Dan) + args("args: [Storage, crud/update, (key, value)]") + invSub(sub: Alice) + prf("proofs") + end + + invIss --> del2Aud + invoker --> invIss + args --> del2Cap + invSub --> del2Sub + rootIss --> subject + rootSub --> subject + prf --> Delegations +``` + +## Signature Validation +[Signature Validation]: #signature-validation + +The [Signature] field MUST validate against the `iss` DID from the [Payload]. + +# Acknowledgments +[Acknowledgments]: #acknowledgments + +Thank you to [Brendan O'Brien] for real-world feedback, technical collaboration, and implementing the first Golang UCAN library. + +Many thanks to [Hugo Dias], [Mikael Rogers], and the entire DAG House team for the real world feedback, and finding inventive new use cases. + +Thank you [Blaine Cook] for the real-world feedback, ideas on future features, and lessons from other auth standards. + +Many thanks to [Brian Ginsburg] and [Steven Vandevelde] for their many copy edits, feedback from real world usage, maintenance of the TypeScript implementation, and tools such as [ucan.xyz]. + +Many thanks to [Christopher Joel] for his real-world feedback, raising many pragmatic considerations, and the Rust implementation and related crates. + +Many thanks to [Christine Lemmer-Webber] for her handwritten(!) feedback on the design of UCAN, spearheading the [OCapN] initiative, and her related work on [ZCAP-LD]. + +Thanks to [Benjamin Goering] for the many community threads and connections to [W3C] standards. + +Thanks to [Michael Muré] and [Steve Moyer] at [Infura] for their detailed feedback on the selector design and thoughts on ANBF codegen, and an updated Golang UCAN implementation. + +Thanks to [Juan Caballero] for the numerous questions, clarifications, and general advice on putting together a comprehensible spec. + +Thank you [Dan Finlay] for being sufficiently passionate about [OCAP] that we realized that capability systems had a real chance of adoption in an ACL-dominated world. + +Thanks to the entire [SPKI WG][SPKI/SDSI] for their closely related pioneering work. + +Many thanks to [Alan Karp] for sharing his vast experience with capability-based authorization, patterns, and many right words for us to search for. + +We want to especially recognize [Mark Miller] for his numerous contributions to the field of distributed auth, programming languages, and computer security writ large. + + + +[ABNF]: https://datatracker.ietf.org/doc/html/rfc5234 +[Alan Karp]: https://github.com/alanhkarp +[BCP 14]: https://www.rfc-editor.org/info/bcp14 +[Benjamin Goering]: https://github.com/gobengo +[Blaine Cook]: https://github.com/blaine +[Bluesky]: https://blueskyweb.xyz/ +[Brendan O'Brien]: https://github.com/b5 +[Brian Ginsburg]: https://github.com/bgins +[Brooklyn Zelenka]: https://github.com/expede +[CIDv1]: https://github.com/multiformats/cid?tab=readme-ov-file#cidv1 +[Christine Lemmer-Webber]: https://github.com/cwebber +[Christopher Joel]: https://github.com/cdata +[Common Tools]: https://common.tools/ +[DAG-CBOR]: https://ipld.io/specs/codecs/dag-cbor/spec/ +[DAG-JSON]: https://ipld.io/specs/codecs/dag-json/spec/ +[DID fragment]: https://www.w3.org/TR/did-core/#terminology +[DID]: https://www.w3.org/TR/did-core/ +[Dan Finlay]: https://github.com/danfinlay +[Daniel Holmgren]: https://github.com/dholms +[ES256]: https://www.rfc-editor.org/rfc/rfc7518#section-3.4 +[EdDSA]: https://en.wikipedia.org/wiki/EdDSA +[Executor]: https://github.com/ucan-wg/spec#31-roles +[Fission]: https://fission.codes +[High Level Command]: https://github.com/ucan-wg/spec#33-command +[Hugo Dias]: https://github.com/hugomrdias +[IEEE-754]: https://ieeexplore.ieee.org/document/8766229 +[IPLD]: https://ipld.io/ +[Infura]: https://www.infura.io/ +[Ink & Switch]: https://www.inkandswitch.com/ +[Invocation]: https://github.com/ucan-wg/invocation +[Irakli Gozalishvili]: https://github.com/Gozala +[JS Number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number +[Juan Caballero]: https://github.com/bumblefudge +[Mark Miller]: https://github.com/erights +[Martin Kleppmann]: https://martin.kleppmann.com/ +[Michael Muré]: https://github.com/MichaelMure +[Mikael Rogers]: https://github.com/mikeal/ +[OCAP]: https://en.wikipedia.org/wiki/Object-capability_model +[OCapN]: https://github.com/ocapn/ +[Philipp Krüger]: https://github.com/matheus23 +[PoLA]: https://en.wikipedia.org/wiki/Principle_of_least_privilege +[Powerbox]: https://sandstorm.io/how-it-works#powerbox +[Protocol Labs]: https://protocol.ai/ +[RFC 3339]: https://www.rfc-editor.org/rfc/rfc3339 +[RFC 8037]: https://www.rfc-editor.org/rfc/rfc8037 +[RS256]: https://www.rfc-editor.org/rfc/rfc7518#section-3.3 +[Raw data multicodec]: https://github.com/multiformats/multicodec/blob/master/table.csv#L41 +[Revocation]: https://github.com/ucan-wg/revocation +[SHA2-256]: https://github.com/multiformats/multicodec/blob/master/table.csv#L9 +[SPKI/SDSI]: https://datatracker.ietf.org/wg/spki/about/ +[SPKI]: https://theworld.com/~cme/html/spki.html +[Steve Moyer]: https://github.com/smoyer64 +[Steven Vandevelde]: https://github.com/icidasset +[UCAN Envelope]: https://github.com/ucan-wg/spec/blob/high-level/README.md#envelope +[UCAN Invocation]: https://github.com/ucan-wg/invocation +[UCAN]: https://github.com/ucan-wg/spec +[Varsig]: https://github.com/ChainAgnostic/varsig +[W3C]: https://www.w3.org/ +[Witchcraft Software]: https://github.com/expede +[ZCAP-LD]: https://w3c-ccg.github.io/zcap-spec/ +[`did:key`]: https://w3c-ccg.github.io/did-method-key/ +[`did:plc`]: https://github.com/did-method-plc/did-method-plc +[`did:web`]: https://w3c-ccg.github.io/did-method-web/ +[base32]: https://github.com/multiformats/multibase/blob/master/multibase.csv#L13 +[dag-json multicodec]: https://github.com/multiformats/multicodec/blob/master/table.csv#L112 +[did-spec]: https://www.w3.org/TR/did-core/ +[did:key ECDSA]: https://w3c-ccg.github.io/did-method-key/#p-256 +[did:key EdDSA]: https://w3c-ccg.github.io/did-method-key/#ed25519-x25519 +[did:key RSA]: https://w3c-ccg.github.io/did-method-key/#rsa +[external resource]: https://github.com/ucan-wg/spec#55-wrapping-existing-systems +[jq]: https://jqlang.github.io/jq/ +[number zero]: https://n0.computer/ +[revocation]: https://github.com/ucan-wg/revocation +[ucan.xyz]: https://ucan.xyz diff --git a/Scope.md b/Scope.md new file mode 100644 index 0000000..6baaada --- /dev/null +++ b/Scope.md @@ -0,0 +1,5 @@ +# Scope + +This document specifies a chained authorization certificate format. It is applicable to capability-based authorization and cryptographic challenge-responses for networked, peer-to-peer, Cloud, offline, local-first, cross-application, and blockchain use cases where capabilities need to be shared between principals without transmitting private key material. + +Any changes of Scope are not retroactive. diff --git a/delegation.ipldsch b/delegation.ipldsch new file mode 100644 index 0000000..f0b1c05 --- /dev/null +++ b/delegation.ipldsch @@ -0,0 +1,27 @@ +type Delegation struct { + p SignaturePayload + s Signature +} + +type DelegationPayload struct { + iss DID + aud DID + sub DID + + exp Integer + nbf Integer + + can String + args {String : Any} + cond [{String : Any}] +} + +type Signature union { + | batch BatchSig + | inline Bytes +} representation kinded + +type BatchSig struct { + scp &[Any] + sig Bytes +}