diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..1faa908 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,9 @@ +# Specification License + +Specifications in this repository are subject to the W3C Patent Policy (2004), available at http://www.w3.org/Consortium/Patent-Policy-20040205. + +# 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 Apache 2.0 license, available at http://www.apache.org/licenses/LICENSE-2.0.html, unless otherwise designated. In the case of any conflict or confusion within this specification repository between the W3C Patent Policy (2004) or other designated license, the terms of the W3C Patent Policy (2004) shall apply. + +These terms are inherited from the Decentralized Identity Foundation Project Charter, available at https://github.com/decentralized-identity/org/blob/master/Org%20documents/Membership%20agreements/DIF%20Project%20Charter%20_4.0.2.pdf diff --git a/README.md b/README.md new file mode 100644 index 0000000..8d9c23d --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +# Trust DID Web - A DID Method + +The spec repository for did:tdw -- Trust DID Web DID method. + +Read the spec: [https://identity.foundation/trustdidweb](https://identity.foundation/trustdidweb) + +Proof of concept implementations available: + +- Typescript: [https://github.com/bcgov/trustdidweb-ts](https://github.com/bcgov/trustdidweb-ts) +- Python: [https://github.com/bcgov/trustdidweb-py](https://github.com/bcgov/trustdidweb-py) +- Go: [https://github.com/nuts-foundation/trustdidweb-go](https://github.com/nuts-foundation/trustdidweb-go) + +## Abstract + +The `did:tdw` (Trust DID Web) method is an enhancement to the +`did:web` protocol, providing a complementary web-based DID method that addresses limitations +of `did:web`. It's features include the following. + +- Ongoing publishing of all DID Document (DIDDoc) versions for a DID instead of, + or alongside a `did:web` DID/DIDDoc. +- Uses the same DID-to-HTTPS transformation as `did:web`. +- Provides resolvers the full history of the DID using a verifiable chain of + updates to the DIDDoc from genesis to deactivation. +- A self-certifying identifier (SCID) for the DID that is globally + unique and derived from the initial DIDDoc that enables DID portability, such + as moving the DIDs web location (and so the DID string itself) while retaining + the DID's history. +- DIDDoc updates include a proof signed by the DID Controller(s) *authorized* to + update the DID. +- An optional mechanism for publishing "pre-rotation" keys to prevent loss of + control of the DID in cases where an active private key is compromised. +- An optional mechanism for having collaborating "witnesses" + that approve updates to the DID by the DID Controller before publication. +- DID URL path handling that defaults (but can be overridden) to automatically + resolving `/path/to/file` by using a comparable DID-to-HTTPS translation + as for the DIDDoc. +- A DID URL path `/whois` that defaults to automatically returning (if + published by the DID controller) a Verifiable Presentation containing + Verifiable Credentials with the DID as the `credentialSubject`, + signed by the DID. + +Combined, the additional features enable greater trust and security without +compromising the simplicity of `did:web`. The incorporation of the DID Core +compatible "/whois" path, drawing inspiration from the traditional WHOIS +protocol, offers an easy to use, decentralized, trust registry. +This `did:tdw` aims to establish a more trusted and secure web environment by +providing robust verification processes and enabling transparency and +authenticity in the management of decentralized digital identities. + +## Contributing to the Specification + +Pull requests (PRs) to this repository may be accepted. Each commit of a PR must +have a DCO (Developer Certificate of Origin - +[https://github.com/apps/dco](https://github.com/apps/dco)) sign-off. This can +be done from the command line by adding the `-s` (lower case) option on the `git +commit` command (e.g., `git commit -s -m "Comment about the commit"`). + +Rendering and reviewing the spec locally for testing requires `npm` and `node` +installed. Follow these steps: + +- Fork and locally clone the repository. +- Install `node` and `npm`. +- Run `npm install` from the root of your local repository. +- Edit the spec documents (in the `/spec` folder). +- Run `npm run render`' + - Use `npm run edit` to interactively edit, render and review the spec. +- Review the resulting `index.html` file in a browser. + +The specification is currently in +[Spec-Up](https://github.com/decentralized-identity/spec-up) format. See the +[Spec-Up Documentation](https://identity.foundation/spec-up/) for a list of +Spec-Up features and functionality. diff --git a/agenda.md b/agenda.md new file mode 100644 index 0000000..a955020 --- /dev/null +++ b/agenda.md @@ -0,0 +1,41 @@ +# trustdidweb - rolling agenda & minutes + +[![hackmd-github-sync-badge](https://hackmd.io/3aEr9Zp_T8GziXQEpah4Gg/badge)](https://hackmd.io/3aEr9Zp_T8GziXQEpah4Gg) + + +[**WG projects** ](https://github.com/decentralized-identity?q=wg-id&type=&language=) | [ DIF page ](https://identity.foundation/working-groups/identifiers-discovery.html) | [Mailing list and Wiki ](https://lists.identity.foundation/g/cc-id) | [Meeting recordings](https://docs.google.com/spreadsheets/d/1wgccmMvIImx30qVE9GhRKWWv3vmL2ZyUauuKx3IfRmA/edit?gid=111226877#gid=111226877) + +_For this call, you are encouraged to turn your video on. This is a good way to build rapport given we are a large, disparate group experiencing a lot of churn._ + +_This document is live-edited DURING each call, and stable/authoritative copies live on our github repo under /agenda.md . +Please note that we might not notice a pullrequest in time, but you are free to propose agenda items for future meetings via hackmd._ + +
+ Meeting information + +- Before you contribute + - [**Join DIF**](https://identity.foundation/join) and [sign the WG charter](https://bit.ly/DIF-WG-select1) (both are required!) + - [**Refer to DIF's code of conduct**](https://github.com/decentralized-identity/org/blob/master/code-of-conduct.md) +- Time: 9am PT, Thursdays bi-weekly +- [Calendar entry](https://calendar.google.com/event?action=TEMPLATE&tmeid=NG5jYWowbmZsdWNzM21tYjBsbDIzdG50ZzFfMjAyNDA5MTJUMTYwMDAwWiBkZWNlbnRyYWxpemVkLmlkZW50aXR5QG0&tmsrc=decentralized.identity%40gmail.com&scp=ALL) +- [Zoom room](https://us02web.zoom.us/j/83119969275?pwd=IZTuXgGLtdLPjPLuB6q8zHXazxHSsU.1) +
+ +#### Future topics: + +
+ Topics for upcoming meetings + +- topic 1 (to be discussed on this date) +- topic 2 (to be discussed on this date) +- topic n. (tbd) + +
+ +## Meeting - 12 Sept 2024 - (1200 ET) + +1. Welcome and introductions +2. [WG participation tracking](https://docs.google.com/spreadsheets/d/12hFa574v5PRrKfzIKMgDTjxuU6lvtBhrmLspfKkN4oE/edit#gid=0) +3. Review of issues and pull requests +4. Main topics +5. Action item and next steps diff --git a/didtdw_light.jpg b/didtdw_light.jpg new file mode 100644 index 0000000..3109207 Binary files /dev/null and b/didtdw_light.jpg differ diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..9889a87 Binary files /dev/null and b/favicon.ico differ diff --git a/fonts/KaTeX_AMS-Regular.ttf b/fonts/KaTeX_AMS-Regular.ttf new file mode 100644 index 0000000..737cf8e Binary files /dev/null and b/fonts/KaTeX_AMS-Regular.ttf differ diff --git a/fonts/KaTeX_AMS-Regular.woff b/fonts/KaTeX_AMS-Regular.woff new file mode 100644 index 0000000..38378bf Binary files /dev/null and b/fonts/KaTeX_AMS-Regular.woff differ diff --git a/fonts/KaTeX_AMS-Regular.woff2 b/fonts/KaTeX_AMS-Regular.woff2 new file mode 100644 index 0000000..a4d1ba6 Binary files /dev/null and b/fonts/KaTeX_AMS-Regular.woff2 differ diff --git a/fonts/KaTeX_Caligraphic-Bold.ttf b/fonts/KaTeX_Caligraphic-Bold.ttf new file mode 100644 index 0000000..04d28ab Binary files /dev/null and b/fonts/KaTeX_Caligraphic-Bold.ttf differ diff --git a/fonts/KaTeX_Caligraphic-Bold.woff b/fonts/KaTeX_Caligraphic-Bold.woff new file mode 100644 index 0000000..a01ce90 Binary files /dev/null and b/fonts/KaTeX_Caligraphic-Bold.woff differ diff --git a/fonts/KaTeX_Caligraphic-Bold.woff2 b/fonts/KaTeX_Caligraphic-Bold.woff2 new file mode 100644 index 0000000..3792727 Binary files /dev/null and b/fonts/KaTeX_Caligraphic-Bold.woff2 differ diff --git a/fonts/KaTeX_Caligraphic-Regular.ttf b/fonts/KaTeX_Caligraphic-Regular.ttf new file mode 100644 index 0000000..b2ce555 Binary files /dev/null and b/fonts/KaTeX_Caligraphic-Regular.ttf differ diff --git a/fonts/KaTeX_Caligraphic-Regular.woff b/fonts/KaTeX_Caligraphic-Regular.woff new file mode 100644 index 0000000..bc169b7 Binary files /dev/null and b/fonts/KaTeX_Caligraphic-Regular.woff differ diff --git a/fonts/KaTeX_Caligraphic-Regular.woff2 b/fonts/KaTeX_Caligraphic-Regular.woff2 new file mode 100644 index 0000000..f1e38bb Binary files /dev/null and b/fonts/KaTeX_Caligraphic-Regular.woff2 differ diff --git a/fonts/KaTeX_Fraktur-Bold.ttf b/fonts/KaTeX_Fraktur-Bold.ttf new file mode 100644 index 0000000..c42d169 Binary files /dev/null and b/fonts/KaTeX_Fraktur-Bold.ttf differ diff --git a/fonts/KaTeX_Fraktur-Bold.woff b/fonts/KaTeX_Fraktur-Bold.woff new file mode 100644 index 0000000..f30b54b Binary files /dev/null and b/fonts/KaTeX_Fraktur-Bold.woff differ diff --git a/fonts/KaTeX_Fraktur-Bold.woff2 b/fonts/KaTeX_Fraktur-Bold.woff2 new file mode 100644 index 0000000..b7a8359 Binary files /dev/null and b/fonts/KaTeX_Fraktur-Bold.woff2 differ diff --git a/fonts/KaTeX_Fraktur-Regular.ttf b/fonts/KaTeX_Fraktur-Regular.ttf new file mode 100644 index 0000000..4133228 Binary files /dev/null and b/fonts/KaTeX_Fraktur-Regular.ttf differ diff --git a/fonts/KaTeX_Fraktur-Regular.woff b/fonts/KaTeX_Fraktur-Regular.woff new file mode 100644 index 0000000..5af51de Binary files /dev/null and b/fonts/KaTeX_Fraktur-Regular.woff differ diff --git a/fonts/KaTeX_Fraktur-Regular.woff2 b/fonts/KaTeX_Fraktur-Regular.woff2 new file mode 100644 index 0000000..3874f93 Binary files /dev/null and b/fonts/KaTeX_Fraktur-Regular.woff2 differ diff --git a/fonts/KaTeX_Main-Bold.ttf b/fonts/KaTeX_Main-Bold.ttf new file mode 100644 index 0000000..14390e0 Binary files /dev/null and b/fonts/KaTeX_Main-Bold.ttf differ diff --git a/fonts/KaTeX_Main-Bold.woff b/fonts/KaTeX_Main-Bold.woff new file mode 100644 index 0000000..33b4199 Binary files /dev/null and b/fonts/KaTeX_Main-Bold.woff differ diff --git a/fonts/KaTeX_Main-Bold.woff2 b/fonts/KaTeX_Main-Bold.woff2 new file mode 100644 index 0000000..f9b71cb Binary files /dev/null and b/fonts/KaTeX_Main-Bold.woff2 differ diff --git a/fonts/KaTeX_Main-BoldItalic.ttf b/fonts/KaTeX_Main-BoldItalic.ttf new file mode 100644 index 0000000..ad0761f Binary files /dev/null and b/fonts/KaTeX_Main-BoldItalic.ttf differ diff --git a/fonts/KaTeX_Main-BoldItalic.woff b/fonts/KaTeX_Main-BoldItalic.woff new file mode 100644 index 0000000..115af4f Binary files /dev/null and b/fonts/KaTeX_Main-BoldItalic.woff differ diff --git a/fonts/KaTeX_Main-BoldItalic.woff2 b/fonts/KaTeX_Main-BoldItalic.woff2 new file mode 100644 index 0000000..5c500c2 Binary files /dev/null and b/fonts/KaTeX_Main-BoldItalic.woff2 differ diff --git a/fonts/KaTeX_Main-Italic.ttf b/fonts/KaTeX_Main-Italic.ttf new file mode 100644 index 0000000..fc8625c Binary files /dev/null and b/fonts/KaTeX_Main-Italic.ttf differ diff --git a/fonts/KaTeX_Main-Italic.woff b/fonts/KaTeX_Main-Italic.woff new file mode 100644 index 0000000..2d3087a Binary files /dev/null and b/fonts/KaTeX_Main-Italic.woff differ diff --git a/fonts/KaTeX_Main-Italic.woff2 b/fonts/KaTeX_Main-Italic.woff2 new file mode 100644 index 0000000..08510d8 Binary files /dev/null and b/fonts/KaTeX_Main-Italic.woff2 differ diff --git a/fonts/KaTeX_Main-Regular.ttf b/fonts/KaTeX_Main-Regular.ttf new file mode 100644 index 0000000..5115a04 Binary files /dev/null and b/fonts/KaTeX_Main-Regular.ttf differ diff --git a/fonts/KaTeX_Main-Regular.woff b/fonts/KaTeX_Main-Regular.woff new file mode 100644 index 0000000..42b74ab Binary files /dev/null and b/fonts/KaTeX_Main-Regular.woff differ diff --git a/fonts/KaTeX_Main-Regular.woff2 b/fonts/KaTeX_Main-Regular.woff2 new file mode 100644 index 0000000..18647fa Binary files /dev/null and b/fonts/KaTeX_Main-Regular.woff2 differ diff --git a/fonts/KaTeX_Math-BoldItalic.ttf b/fonts/KaTeX_Math-BoldItalic.ttf new file mode 100644 index 0000000..326b523 Binary files /dev/null and b/fonts/KaTeX_Math-BoldItalic.ttf differ diff --git a/fonts/KaTeX_Math-BoldItalic.woff b/fonts/KaTeX_Math-BoldItalic.woff new file mode 100644 index 0000000..5b4041a Binary files /dev/null and b/fonts/KaTeX_Math-BoldItalic.woff differ diff --git a/fonts/KaTeX_Math-BoldItalic.woff2 b/fonts/KaTeX_Math-BoldItalic.woff2 new file mode 100644 index 0000000..ba55276 Binary files /dev/null and b/fonts/KaTeX_Math-BoldItalic.woff2 differ diff --git a/fonts/KaTeX_Math-Italic.ttf b/fonts/KaTeX_Math-Italic.ttf new file mode 100644 index 0000000..f148fce Binary files /dev/null and b/fonts/KaTeX_Math-Italic.ttf differ diff --git a/fonts/KaTeX_Math-Italic.woff b/fonts/KaTeX_Math-Italic.woff new file mode 100644 index 0000000..31d0038 Binary files /dev/null and b/fonts/KaTeX_Math-Italic.woff differ diff --git a/fonts/KaTeX_Math-Italic.woff2 b/fonts/KaTeX_Math-Italic.woff2 new file mode 100644 index 0000000..9871ab6 Binary files /dev/null and b/fonts/KaTeX_Math-Italic.woff2 differ diff --git a/fonts/KaTeX_SansSerif-Bold.ttf b/fonts/KaTeX_SansSerif-Bold.ttf new file mode 100644 index 0000000..dce35c8 Binary files /dev/null and b/fonts/KaTeX_SansSerif-Bold.ttf differ diff --git a/fonts/KaTeX_SansSerif-Bold.woff b/fonts/KaTeX_SansSerif-Bold.woff new file mode 100644 index 0000000..992cb3d Binary files /dev/null and b/fonts/KaTeX_SansSerif-Bold.woff differ diff --git a/fonts/KaTeX_SansSerif-Bold.woff2 b/fonts/KaTeX_SansSerif-Bold.woff2 new file mode 100644 index 0000000..6dd1038 Binary files /dev/null and b/fonts/KaTeX_SansSerif-Bold.woff2 differ diff --git a/fonts/KaTeX_SansSerif-Italic.ttf b/fonts/KaTeX_SansSerif-Italic.ttf new file mode 100644 index 0000000..a3eb86c Binary files /dev/null and b/fonts/KaTeX_SansSerif-Italic.ttf differ diff --git a/fonts/KaTeX_SansSerif-Italic.woff b/fonts/KaTeX_SansSerif-Italic.woff new file mode 100644 index 0000000..f4fa252 Binary files /dev/null and b/fonts/KaTeX_SansSerif-Italic.woff differ diff --git a/fonts/KaTeX_SansSerif-Italic.woff2 b/fonts/KaTeX_SansSerif-Italic.woff2 new file mode 100644 index 0000000..9f2501a Binary files /dev/null and b/fonts/KaTeX_SansSerif-Italic.woff2 differ diff --git a/fonts/KaTeX_SansSerif-Regular.ttf b/fonts/KaTeX_SansSerif-Regular.ttf new file mode 100644 index 0000000..3be73ce Binary files /dev/null and b/fonts/KaTeX_SansSerif-Regular.ttf differ diff --git a/fonts/KaTeX_SansSerif-Regular.woff b/fonts/KaTeX_SansSerif-Regular.woff new file mode 100644 index 0000000..ec283f4 Binary files /dev/null and b/fonts/KaTeX_SansSerif-Regular.woff differ diff --git a/fonts/KaTeX_SansSerif-Regular.woff2 b/fonts/KaTeX_SansSerif-Regular.woff2 new file mode 100644 index 0000000..e46094f Binary files /dev/null and b/fonts/KaTeX_SansSerif-Regular.woff2 differ diff --git a/fonts/KaTeX_Script-Regular.ttf b/fonts/KaTeX_Script-Regular.ttf new file mode 100644 index 0000000..40c8a99 Binary files /dev/null and b/fonts/KaTeX_Script-Regular.ttf differ diff --git a/fonts/KaTeX_Script-Regular.woff b/fonts/KaTeX_Script-Regular.woff new file mode 100644 index 0000000..4eafae7 Binary files /dev/null and b/fonts/KaTeX_Script-Regular.woff differ diff --git a/fonts/KaTeX_Script-Regular.woff2 b/fonts/KaTeX_Script-Regular.woff2 new file mode 100644 index 0000000..69b1754 Binary files /dev/null and b/fonts/KaTeX_Script-Regular.woff2 differ diff --git a/fonts/KaTeX_Size1-Regular.ttf b/fonts/KaTeX_Size1-Regular.ttf new file mode 100644 index 0000000..f0aff83 Binary files /dev/null and b/fonts/KaTeX_Size1-Regular.ttf differ diff --git a/fonts/KaTeX_Size1-Regular.woff b/fonts/KaTeX_Size1-Regular.woff new file mode 100644 index 0000000..0358ee4 Binary files /dev/null and b/fonts/KaTeX_Size1-Regular.woff differ diff --git a/fonts/KaTeX_Size1-Regular.woff2 b/fonts/KaTeX_Size1-Regular.woff2 new file mode 100644 index 0000000..f951ed0 Binary files /dev/null and b/fonts/KaTeX_Size1-Regular.woff2 differ diff --git a/fonts/KaTeX_Size2-Regular.ttf b/fonts/KaTeX_Size2-Regular.ttf new file mode 100644 index 0000000..4f72f16 Binary files /dev/null and b/fonts/KaTeX_Size2-Regular.ttf differ diff --git a/fonts/KaTeX_Size2-Regular.woff b/fonts/KaTeX_Size2-Regular.woff new file mode 100644 index 0000000..8a053d2 Binary files /dev/null and b/fonts/KaTeX_Size2-Regular.woff differ diff --git a/fonts/KaTeX_Size2-Regular.woff2 b/fonts/KaTeX_Size2-Regular.woff2 new file mode 100644 index 0000000..181d962 Binary files /dev/null and b/fonts/KaTeX_Size2-Regular.woff2 differ diff --git a/fonts/KaTeX_Size3-Regular.ttf b/fonts/KaTeX_Size3-Regular.ttf new file mode 100644 index 0000000..56d2dc6 Binary files /dev/null and b/fonts/KaTeX_Size3-Regular.ttf differ diff --git a/fonts/KaTeX_Size3-Regular.woff b/fonts/KaTeX_Size3-Regular.woff new file mode 100644 index 0000000..0ec99ad Binary files /dev/null and b/fonts/KaTeX_Size3-Regular.woff differ diff --git a/fonts/KaTeX_Size3-Regular.woff2 b/fonts/KaTeX_Size3-Regular.woff2 new file mode 100644 index 0000000..c2985cd Binary files /dev/null and b/fonts/KaTeX_Size3-Regular.woff2 differ diff --git a/fonts/KaTeX_Size4-Regular.ttf b/fonts/KaTeX_Size4-Regular.ttf new file mode 100644 index 0000000..baf0209 Binary files /dev/null and b/fonts/KaTeX_Size4-Regular.ttf differ diff --git a/fonts/KaTeX_Size4-Regular.woff b/fonts/KaTeX_Size4-Regular.woff new file mode 100644 index 0000000..ff67319 Binary files /dev/null and b/fonts/KaTeX_Size4-Regular.woff differ diff --git a/fonts/KaTeX_Size4-Regular.woff2 b/fonts/KaTeX_Size4-Regular.woff2 new file mode 100644 index 0000000..a4e810d Binary files /dev/null and b/fonts/KaTeX_Size4-Regular.woff2 differ diff --git a/fonts/KaTeX_Typewriter-Regular.ttf b/fonts/KaTeX_Typewriter-Regular.ttf new file mode 100644 index 0000000..e66c218 Binary files /dev/null and b/fonts/KaTeX_Typewriter-Regular.ttf differ diff --git a/fonts/KaTeX_Typewriter-Regular.woff b/fonts/KaTeX_Typewriter-Regular.woff new file mode 100644 index 0000000..c66d149 Binary files /dev/null and b/fonts/KaTeX_Typewriter-Regular.woff differ diff --git a/fonts/KaTeX_Typewriter-Regular.woff2 b/fonts/KaTeX_Typewriter-Regular.woff2 new file mode 100644 index 0000000..e5bf2ce Binary files /dev/null and b/fonts/KaTeX_Typewriter-Regular.woff2 differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..71efcc4 --- /dev/null +++ b/index.html @@ -0,0 +1,2418 @@ + + + + + + + + + Trust DID Web - The did:tdw DID Method + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+

§ Trust DID Web - did:tdw

+

Specification Status: DRAFT

+

Specification Version: 0.3 (see Changelog)

+

Latest Draft: +https://github.com/decentralized-identity/trustdidweb

+
+
Editors:
+
Stephen Curran
+
John Jordan, BC Gov
+
Andrew Whitehead
+
Brian Richter
+
Michel Sahli
+
Martina Kolpondinos
+
Dmitri Zagdulin
+
Participate:
+
GitHub repo
+
File a bug
+
Commit history
+
Implementations:
+
TypeScript
+
Python
+
Go
+
+
+

§ Abstract

+

Trust DID Web (did:tdw) is an enhancement to the did:web DID method, +providing complementary web-based features that address did:web’s +limitations. did:tdw features include:

+
    +
  • Ongoing publishing of all DID Document (DIDDoc) versions for a DID instead of, +or alongside a current did:web DID/DIDDoc.
  • +
  • The same DID-to-HTTPS transformation as did:web.
  • +
  • Supports the same High Assurance DIDs with DNS mechanism.
  • +
  • The ability to resolve the full history of the DID using a verifiable chain of +updates to the DIDDoc from genesis to deactivation.
  • +
  • A self-certifying identifier (SCID) for the DID. The SCID, globally unique and +embedded in the DID, is derived from the initial DID log entry. It ensures the integrity +of the DID’s history mitigating the risk of attackers creating a new object with +the same identifier.
  • +
  • An optional mechanism for enabling DID portability via the SCID, allowing +the DID’s web location to be moved and the DID string to be updated, both while retaining +a connection to the predecessor DID(s) and preserving the DID’s verifiable history.
  • +
  • DIDDoc updates contain a proof signed by the DID Controllers authorized to +update the DID.
  • +
  • An optional mechanism for publishing “pre-rotation” keys to prevent the loss of +control of a DID in cases where an active private key is compromised.
  • +
  • An optional mechanism for having collaborating witnesses +that approve of updates to the DID by a DID Controller before publication.
  • +
  • DID URL path handling that defaults (but can be overridden) to automatically +resolving <did>/path/to/file by using a comparable DID-to-HTTPS translation +as for the DIDDoc.
  • +
  • A DID URL path <did>/whois that defaults to automatically returning (if +published by the DID controller) a Verifiable Presentation containing +Verifiable Credentials with the DID as the credentialSubject, +signed by the DID.
  • +
+

Combined, the additional features enable greater trust and security without +compromising the simplicity of did:web.

+

The incorporation of the DID Core compatible “/whois” path, drawing inspiration +from the traditional WHOIS protocol [RFC3912], offers an easy-to-use, +decentralized, trust registry. The did:tdw method aims to establish a more +trusted and secure web environment by providing robust verification processes +and enabling transparency and authenticity in the management of decentralized +digital identities.

+

§ Definitions

+
+
base58btc
+
Applies [[spec:draft-msporny-base58-03]] to convert +data to a base58 encoding. Used in did:tdw for encoding hashes for SCIDs and entry hashes.
+
Data Integrity
+
W3C Data +Integrity +is a specification of mechanisms for ensuring the authenticity and integrity of +structured digital documents using cryptography, such as digital signatures and +other digital mathematical proofs.
+
Decentralized Identifier
+
Decentralized Identifiers (DIDs) [DID-CORE] are a type of identifier that enable +verifiable, decentralized digital identities. A DID refers to any subject (e.g., +a person, organization, thing, data model, abstract entity, etc.) as determined +by the controller of the DID.
+
DIDDoc
+
A DID Document as defined by the [DID-CORE] – the document returned when a DID is resolved.
+
DID:key
+
DID:key
+
DID Log
+
A DID Log is a list of Entries one being added for each update of an entry item, +including new versions of the DIDDoc or changed information necessary to generate or validate the DID.
+
DID Log Entry
+
A DID Log Entry is a JSON array of five items which define the authorized +transformation of a DIDDoc from one version to the next. The initial entry +establishes the DID and version 1 of the DIDDoc. All entries are stored +in the DID Log.
+
DID Method
+
DID methods are the mechanism by which a particular type of DID and its +associated DID document are created, resolved, updated, and deactivated. DID +methods are defined using separate DID method specifications. This document is +the DID Method Specification for DID:tdw.
+
DID Portability
+
did:tdw portability encompasses the ability to change the DID string for the +DID while retaining the SCID and the history of the DID. This is useful +when forced to change (such as when an organization is acquired by another, +resulting in a change of domain names) and when changing DID hosting service +providers.
+
did:web
+
did:web as described in the W3C specification +is a DID method that leverages the Domain Name System (DNS) to perform the DID operations. +It is valued for its simplicity and ease of deployment compared to DID methods that are +based on distributed ledgers or blockchain technology, but also comes with increased +challenges related to trust and security. did:web provides a starting point for did:tdw, +which complements did:web with specific features to address the challenges +while still providing ease of deployment.
+
eddsa-jcs-2022
+
A cryptosuite defined for producing a Data Integrity proof for an +unsecured input data document and verifying the Data Integrity proof of +the secured document. More information on further operations and applications of +the cryptosuite can be found in the specification, here: +eddsa-jcs-2022
+
Entry Hash
+
A DID:tdw entry hash is a hash generated using a formally defined process +over the input data to a log entry, excluding the Data Integrity proof +item. The input data includes content from the predecessor to the version of the +DID, ensuring that all the versions are “chained” together in a microledger. The +generated entry hash is subsequently included in the versionId element of the log entry and MUST be +verified by a resolver.
+
ISO8601
+
A date/time expressed using the ISO8601 +Standard.
+
JSON Canonicalization Scheme
+
[RFC8785] defines a method for canonicalizing a JSON +structure such that is suitable for verifiable hashing or signing.
+
JSON Lines
+
A file of JSON Lines, as described on the site +https://jsonlines.org/. In short, JSONL is lines of JSON with +whitespace removed and separated by a newline that is convenient for handling +streaming JSON data or log files.
+
JSON Patch
+
[RFC6902] is a web standard format for describing how to change a JSON +document from one state to another. A DID Controller MAY use it in DID:tdw +to define how a DIDDoc is changed from one version to the next.
+
Pre-Rotation
+
A technique for a controller of a cryptographic key to commit to the public +key it will rotate to next, without exposing that actual public key. It protects +from an attacker that gains knowledge of the current private key from being +able to rotate to a new key known only to the attacker.
+
Linked-VP
+
A [DID-CORE] service entry that specifies where a verifiable about the DID subject can be found. The Decentralized Identity +Foundation hosts the Linked VP +Specification.
+
multihash
+
Per the [[spec:draft-multiformats-multihash-07]], multihash is a specification +for differentiating instances of hashes. Software creating a hash prefixes +(according to the specification) data to the hash indicating the algorithm used +and the length of the hash, so that software receiving the hash knows how to +verify it. Although multihash supports many hash algorithms, for +interoperability, DID Controllers MUST only use the hash algorithms defined +in this specification as permitted.
+
multi-sig
+
A cryptographic signature that to be valid MUST contain a defined threshold +(for example, 4 of 7) individual signatures to be considered valid. The +multi-signature key reference points to a verification method that defines what +keys may contribute to the signature, and under what conditions the +multi-signature is considered valid.
+
parameters
+
DID:tdw parameters are a defined set of configurations that control how the +issuer has generated the DID, and how the resolver should process the DID Log. The use of parameters allows for the controlled evolution of DID:tdw +log handling, such as evolving the permitted hash algorithms.
+
self-certifying identifier
+
An object identifier derived from initial data such that an attacker could not +create a new object with the same identifier. The input for a DID:tdw SCID is +the initial DIDDoc with the placeholder {SCID} wherever the SCID is to be +placed.
+
Verifiable Credential
+
A verifiable credential can represent all of the same information that a physical credential represents, adding technologies such as digital signatures, to make the credentials more tamper-evident and so more trustworthy than their physical counterparts. The Verifiable Credential Data Model is a W3C Standard.
+
Verifiable Presentation
+
A verifiable presentation data model is part W3C’s Verifiable Credential Data +Model that contains a set of verifiable credentials about a credentialSubject, and a signature across the +verifiable credentials generated by that subject. In this specification, the use +case of primary interest is where the DID is the credentialSubject and the DID +signs the verifiable presentation.
+
witness
+
Witnesses are participants in the process of creating and verifying a version +of a DID:tdw DIDDoc. Notably, a witness receives from the DID Controller a DID entry ready for publication, verifies it according to this specification, +and approves it according to its ecosystem governance (whatever that might be). If the verification and +approval process results are positive, witnesses returns to the DID Controller a Data Integrity proof +attesting to that positive result.
+
W3C VCDM
+
A Verifiable Credential that uses the Data Model defined by the W3C [[spec: W3C-VC]] specification.
+
+

§ Overview

+

The emergence of Decentralized Identifiers (DIDs) and with them the +evolution of DID Methods continues to be a dynamic area of +development in the quest for trusted, secure and private digital identity +management where the users are in control of their own data.

+

The did:web method, for example, leverages the Domain Name System (DNS) to +perform the DID operations. This approach is praised for its simplicity and +ease of deployment, including DID-to-HTTPS transformation and addressing +some aspects of trust by allowing for DIDs to be associated with a domain’s +reputation or published on platforms such as GitHub. However, it is not +without its challenges– +from trust layers inherited from the web and the absence of a verifiable +history for the DID.

+

Tackling these concerns, the proposed did:tdw (Trust DID Web) +method aims to enhance did:web by introducing additional features such +as a self-certifying identifier (SCID), update key(s) +and a verifiable history, akin to what is available with ledger-based DIDs, +without relying on a ledger.

+

This approach not only maintains backward compatibility but also offers an +additional layer of assurance for those requiring more robust verification +processes. By publishing the resulting DID as both did:web and did:tdw, it +caters to a broader range of trust requirements, from those who are comfortable +with the existing did:web infrastructure to those seeking greater security +assurances provided by did:tdw. This innovative step represents a significant +stride towards a more trusted and secure web, where the integrity of +cryptographic key publishing is paramount.

+

The key differences between did:web and did:tdw revolve around the core +issues of decentralization and security. did:web is recognized for its +simplicity and cost-effectiveness, allowing for easy establishment of a +credential ecosystem. However, it is not inherently decentralized as it relies +on DNS domain names, which require centralized registries. Furthermore, it lacks a +cryptographically verifiable, tamper-resistant, and persistently stored DID +document. In contrast, did:tdw (Trust DID Web) is proposed as an enhancement +to did:web, aiming to address these limitations by adding a verifiable history +to the DID without the need for a ledger. This method seeks to provide a more +decentralized approach by ensuring that the security of the embedded +SCID does not depend on DNS. Additionally, did:tdw is +capable of resolving a cryptographically verifiable trust registry and status +lists, using DID-Linked Resources, which did:web lacks. These features are +designed to build a trusted web, offering a higher level of assurance for +cryptographic key publishing and management.

+

For backwards compatibility, and for verifiers that “trust” did:web, a +did:tdw can be trivially modified and published in parallel to a did:web +DID. For resolvers that want more assurance, did:tdw provides a way to “trust +did:web” (or to enable a “trusted web” if you say it fast) enabled by the +features listed in the Abstract.

+

The following is a tl;dr summary of how did:tdw works:

+
    +
  1. did:tdw uses the same DID-to-HTTPS transformation as did:web, so +did:tdw’s did.jsonl (JSON Lines) file is found in the same +location as did:web’s did.json file, and supports an easy transition +from did:web to gain the added benefits of did:tdw.
  2. +
  3. The did.jsonl is a list of JSON DID log entries, one per line, +whitespace removed (per JSON Lines). Each entry contains the +information needed to derive a version of the DIDDoc from its preceding +version. The did.jsonl is also referred to as the DID Log.
  4. +
  5. Each DID log entry includes a JSON array of five items: +
      +
    1. The versionId of the entry, a value that combines the version number +(starting at 1 and incrementing by one per version), a literal dash +-, and a hash of the entry. The entry hash calculation links each entry +to its predecessor in a ledger-like chain.
    2. +
    3. The versionTime (as stated by the DID Controller) of the entry.
    4. +
    5. A set of parameters that impact the processing of the current and +future log entries. +
        +
      • Example parameters are the version of the did:tdw specification and +hash algorithm being used as well as the SCID and update key(s).
      • +
      +
    6. +
    7. The new version of the DIDDoc as either a value (the full document) or +a patch derived using JSON Patch to update the new version from +the previous entry.
    8. +
    9. A Data Integrity (DI) proof across the entry, signed by a DID authorized to update the DIDDoc, using the versionId as the +challenge.
    10. +
    +
  6. +
  7. In generating the first version of the DIDDoc, the DID Controller calculates +the SCID for the DID from the entire first log entry (which +includes the DIDDoc) by adding the string {SCID} everywhere the actual SCID +is to be placed. The DID Controller then replaces these placeholders +with the just calculated SCID, including it as a parameter in the first log, and inserting it where needed in the initial (and all subsequent) +DIDDocs. The SCID enables an optional portability capability, allowing a DID’s +web location to be moved to a new location while retaining the DID and version +history of the DID.
  8. +
  9. A DID Controller generates and publishes the new/updated DID Log file by making it +available at the appropriate location on the web, based on the identifier of the +DID.
  10. +
  11. Given a did:tdw DID, a resolver converts the DID to an HTTPS URL, +retrieves, and processes the DID Log did.jsonl, generating and verifying +each log entry as per the requirements outlined in this specification. +
      +
    • In the process, the resolver collects all the DIDDoc versions and public +keys used by the DID currently, or in the past. This enables +resolving both current and past versions of the DID.
    • +
    +
  12. +
  13. did:tdw DID URLs with paths and /whois are resolved to documents +published by the DID Controller that are by default in the web location relative to the +did.jsonl file. See the note below about the +powerful capability enabled by the /whois DID URL path.
  14. +
  15. Optionally, a DID Controller can easily generate and publish a did:web DIDDoc +from the latest did:tdw DIDDoc in parallel with the did:tdw DID Log.
  16. +
+
WARNING
A resolver settling for just the `did:web` version of the DID does not get the
+verifiability of the `did:tdw` log.
+
+
+

An example of a did:tdw evolving through a series of versions can be seen in +the did:tdw Examples of this specification.

+

This draft specification was developed in parallel with the development of two +proof of concept implementations. The specification/implementation interplay +helped immensely in defining a practical, intuitive, straightforward, DID +method. The existing proof of concept implementations of the did:tdw DID +Method are listed in the Implementors Guide. The current +implementations range from around 1500 to 2000 lines of code.

+

§ The /whois Use Case

+

This DID Method introduces what we hope will be a widely embraced convention for +all DID Methods – the /whois path. This feature harkens back to the WHOIS +protocol that was created in the 1970s to provide a directory about people and +entities in the early days of ARPANET. In the 80’s, whois evolved into +[RFC920] that has expanded into the global +whois feature we know today as +[RFC3912]. Submit a whois request about a domain name, and get +back the information published about that domain.

+

We propose that the /whois path for a DID enable a comparable, decentralized, +version of the WHOIS protocol for DIDs. Notably, when <did>/whois is +resolved (using a standard DID service that follows the Linked-VP +specification), a Verifiable Presentation (VP) may be returned (if +published by the DID Controller) containing Verifiable Credentials with +the DID as the credentialSubject, and the VP signed by the DID. Given a DID, +one can gather verifiable data about the DID Controller by resolving +<did>/whois and processing the returned VP. That’s powerful – an efficient, +highly decentralized, trust registry. For did:tdw, the approach is very simple +– transform the DID to its HTTPS equivalent, and execute a GET <https>/whois. +Need to know who issued the VCs in the VP? Get the issuer DIDs from those VCs, +and resolve <issuer did>/whois for each. This is comparable to walking a CA +(Certificate Authority) hierarchy, but self-managed by the DID Controllers – +and the issuers that attest to them.

+

The following is a use case for the /whois capability. Consider an example of +the did:tdw controller being a mining company that has exported a shipment and +created a “Product Passport” Verifiable Credential with information about the +shipment. A country importing the shipment (the Importer) might want to know +more about the issuer of the VC, and hence, the details of the shipment. They +resolve the <did>/whois of the entity and get back a Verifiable Presentation +about that DID. It might contain:

+
    +
  • A verifiable credential issued by the Legal Entity Registrar for the +jurisdiction in which the mining company is headquartered. +
      +
    • Since the Importer knows about the Legal Entity Registrar, they can automate +this lookup to get more information about the company from the VC – its +legal name, when it was registered, contact information, etc.
    • +
    +
  • +
  • A verifiable credential for a “Mining Permit” issued by the mining authority +for the jurisdiction in which the company operates. +
      +
    • Perhaps the Importer does not know about the mining authority for that +jurisdiction. The Importer can repeat the /whois resolution process for +the issuer of that credential. The Importer might (for example), resolve +and verify the did:tdw DID for the Authority, and then resolve the +/whois DID URL to find a verifiable credential issued by the government of +the jurisdiction. The Importer recognizes and trusts that government’s +authority, and so can decide to recognize and trust the mining permit +authority.
    • +
    +
  • +
  • A verifiable credential about the auditing of the mining practices of the +mining company. Again, the Importer doesn’t know about the issuer of the audit +VC, so they resolve the /whois for the DID of the issuer, get its VP and +find that it is accredited to audit mining companies by the London Metal +Exchange according to one of its mining standards. +As the Importer knows about both the London Metal Exchange and the standard, +it can make a trust decision about the original Product Passport Verifiable +Credential.
  • +
+

Such checks can all be done with a handful of HTTPS requests and the processing +of the DIDs and verifiable presentations. If the system cannot automatically +make a trust decision, lots of information has been quickly collected that can +be passed to a person to make such a decision.

+

The result is an efficient, verifiable, credential-based, decentralized, +multi-domain trust registry, empowering individuals and organizations to verify +the authenticity and legitimacy of DIDs. The convention promotes a decentralized +trust model where trust is established through cryptographic verification rather +than reliance on centralized authorities. By enabling anyone to access and +validate the information associated with a DID, the “/whois” path contributes to +the overall security and integrity of decentralized networks.

+

§ did:tdw DID Method Specification

+

§ Target System

+

The target system of the Trust DID Web (TDW) DID method is the host (or domain) +name when the domain specified by the DID is resolved through the Domain Name +System (DNS) and verified by processing a log of DID versions.

+

§ Method Name

+

The namestring that identifies this DID method is: tdw. A DID that uses this +method MUST begin with the following prefix: did:tdw. Per the DID +specification, this string MUST be in lowercase. The remainder of the DID, after +the prefix, is the method-specific identifier, +specified below.

+

§ Method-Specific Identifier

+

The did:tdw method-specific identifier contains both the self-certifying identifier (SCID) for the DID, and a fully qualified domain +name (with an optional path) that is secured by a TLS/SSL certificate. Given the +DID, a transformation to an HTTPS URL can be +performed such that the DID Log for the did:tdw DID is retrieved (via +an HTTP GET) and processed to produce the DIDDoc for the DID. As per the +Augmented Backus-Naur Form (ABNF) notation below, the SCID MUST be the first element of +the method-specific identifier.

+

Formal rules describing valid domain name syntax are described in +[RFC1035], [RFC1123], and [RFC2181]. Each did:tdw DID’s +globally unique SCID is generated +during the creation of the DID based on its initial content and placed into +the DID identifier for publication and use.

+

The domain name element of the method-specific identifier MUST match the +common name used in the SSL/TLS certificate, and it MUST NOT include IP +addresses. A port MAY be included and the colon MUST be percent encoded to +prevent a conflict with paths. Directories and subdirectories MAY optionally be +included, delimited by colons rather than slashes.

+

As specified in the following Augmented Backus-Naur Form (ABNF) notation +[RFC2234] the SCID MUST be present in the DID string. See +examples below. The domain-segment and path-segment elements refer to +[RFC3986]’s ABNF for a Generic URL (page 49). Attempting to replicate +here the full ABNF of those elements from that RFC would inevitably be wrong.

+
tdw-did = "did:tdw:" scid ":" domain-segment 1+( "." domain-segment ) *( ":" path-segment )
+domain-segment = ; A part of a domain name as defined in RFC3986, such as "example" and "com" in "example.com"
+path-segment= ; A part of a URL path as defined in RFC3986, such as "path", "to", "folder" in "path/to/folder"
+
+

The ABNF for a did:tdw is almost identical to that of did:web, with changes only to +the DID Method (tdw instead of web), and the addition of the <scid>: +element in did:tdw that is not in did:web. As specified in the DID-to-HTTPS +Transformation section of this specification, +did:tdw and did:web DIDs that have the same fully qualified domain and path +transform to the same HTTPS URL, with the exception of the final file – +did.json for did:web and did.jsonl for did:tdw.

+

§ The DID to HTTPS Transformation

+

The did:tdw method-specific identifier is +defined to enable a transformation of the DID to an HTTPS URL for publishing +and retrieving the DID Log. This section defines the transformation +from DID to HTTPS URL, including a number of examples.

+

Given a did:tdw, the HTTPS URL for the DID Log is generated by +carrying out the following steps. The steps are carried out by the DID to determine where to publish the DID Log, and by all resolvers to +retrieve the DID Log.

+
    +
  1. Remove the literal did:tdw: prefix from the DID, leaving the method specific +identifier.
  2. +
  3. Remove the SCID by removing the text up to and including the first colon +(<scid>:) from the method-specific identifier and continue processing.
  4. +
  5. Replace : with / in the method-specific identifier to obtain the fully +qualified domain name and optional path.
  6. +
  7. If there is no optional path, append /.well-known to the URL. +
      +
    1. When this algorithm is used for resolving a DID path (such as +<did>/whois or <did>/path/to/file as defined in the section [DID URL Handling](#did-url-resolution)), the /.well-known` MUST NOT be +included in the HTTPS URL.
    2. +
    +
  8. +
  9. If the domain contains a port, percent decode the colon.
  10. +
  11. Generate an HTTPS URL to the expected location of the DIDDoc by prepending +https://.
  12. +
  13. Append /did.jsonl to complete the URL. +
      +
    1. When this algorithm is used for resolving a DID path (such as +<did>/whois or `/path/to/file as defined in the section DID URL +Handling), append the DID URL path instead.
    2. +
    +
  14. +
+

The following are some examples of various DID-to-HTTPS transformations based +on the processing steps specified above.

+
EXAMPLE

did:tdw DIDs and the corresponding web locations of their did:tdw log file. +In the examples,{SCID} is a placeholder for where the generated SCID would be +placed in the actual DIDs and HTTPS URLs. Note that when the {SCID} follows +the literal did:tdw: as a separate element, the {SCID} is not part of the +HTTPS URL.

+
+

domain/did:web-compatible

+

did:tdw:{SCID}:example.com -->

+

https://example.com/.well-known/did.jsonl

+

subdomain

+

did:tdw:{SCID}:issuer.example.com -->

+

https://issuer.example.com/.well-known/did.jsonl

+

path

+

did:tdw:{SCID}:example.com:dids:issuer -->

+

https://example.com/dids/issuer/did.jsonl

+

path w/ port

+

did:tdw:{SCID}:example.com%3A3000:dids:issuer -->

+

https://example.com:3000/dids/issuer/did.jsonl

+
+

The location of the did:tdw did.jsonl DID Log file is the same as +where the comparable did:web did.json file is published. A DID MAY choose to publish both DIDs and so, both files. The process +to do so is described in the publishing a parallel did:web +DID section of this specification.

+

§ The DID Log File

+

The DID log file contains a list of entries, one for each version of the DID. A +version of the DID is an update to the contents of the resolved DIDDoc for the +DID, and/or a change to the parameters that control the generation and +verification of the DID.

+

Each entry is a JSON array consisting of the following 5 items.

+

[ versionId, versionTime, parameters, DIDDoc State, Data Integrity Proof ]

+
    +
  1. The entry versionId is a value that combines the version number (starting at +1 and incrementing by one per DID version), a literal dash -, and the +entryHash, a hash calculated across the log entry content. The input to the +hash is chosen so as to link each entry to its predecessor in a ledger-like +chain. The input to the hash is specified in the Entry Hash Generation and +Verification section of this +specification.
  2. +
  3. The versionTime (as stated by the DID Controller) of the entry, in ISO8601 format.
  4. +
  5. A JSON object parameters that define configurations/options used in the +processing of current and future log entries. parameters are defined in the +did:tdw DID Method Parameters section of +this specification.
  6. +
  7. The DIDDoc State for this version of the DID as either value, the full +DIDDoc, or patch, such that the new DIDDoc is derived using +JSON Patch from the previous entry.
  8. +
  9. A Data Integrity Proof across the entry, signed by a DID authorized to update the DIDDoc, using the versionId as the +challenge.
  10. +
+

After creation, each entry has (per the JSON Lines specification) all +extra whitespace removed, a \n character appended, and the result added to +the DID Log file for publication.

+

A more comprehensive description of how to create a DID log entry and update it +into a JSON Line is given in steps 4 - 6 of the next section.

+

Examples of DID Logs and DID log entries can be found in the +did:tdw` Examples section of this specification.

+

§ DID Method Operations

+

§ Create (Register)

+

Creating a did:tdw DID is done by carrying out the following steps.

+
    +
  1. +

    Define the DID string +The start of the DID MUST be the literal string “did:tdw:{SCID}:”, where the {SCID} is +a placeholder that will be replaced by the calculated SCID later in the process (see step +5). This first part of the DID string is followed by a fully qualified domain name +(with an optional path) that is secured by a TLS/SSL certificate and +reflects the web location at which the DID Log (did.jsonl) will be published

    +

    The DID MUST be a valid did:tdw DID as per the ABNF of a did:tdw DID defined +in the Method-Specific Identifier section of this specification.

    +
      +
    1. Note: the SCID for a did:tdw DID is not by default in the HTTPS URL for the DID. +A DID Controller that wants to include the SCID in the HTTPS URL MAY +add additional placeholder {SCID} strings into the domain name or path +components of the method-specific identifier when creating the DID. The +additional instance(s) of the SCID have no impact on the handling of the +DID, and are treated like any other part of the domain and/or path.
    2. +
    +
  2. +
  3. +

    Generate the authorization key pair(s) +Authorized keys are authorized to control (create, update, deactivate) the DID. +This includes generating any other key pairs that will be placed into the initial +DIDDoc for the DID.

    +
      +
    1. If the DID is to use pre-rotation, additional key generation will +be necessary to generate the required “next” authorization keys and their +corresponding pre-rotation hashes.
    2. +
    3. For each authorization key pair, generate a multikey based on the +key pair’s public key. The multikey representations of the public +keys are placed in the updateKeys item in parameters.
    4. +
    5. The public key(s) of the authorization key pair(s) MAY be used in the +DIDDoc as well, but that is not required.
    6. +
    +
  4. +
  5. +

    Create the initial DIDDoc for the DID +The DIDDoc MUST contain the top level id item which MUST be the DID string from +step 1, including the placement of the {SICD} placeholder for the SCID. Other +DIDDoc verifications SHOULD be performed.

    +

    All other absolute self-reference’s to the DID in the DIDDoc must use the form defined +in step 1, with the identified placeholder for the SCID (e.g., did:tdw:{SCID}:example.com#key-1, +did:tdw:{SCID}:example.com:dids:issuer#key-1, etc.). The DIDDoc can contain any other content as deemed necessary by the DID Controller.

    +
      +
    1. Note: The placeholder (the string {SCID}) MUST be in every place in the DIDDoc where +the SCID is to be placed.
    2. +
    +
  6. +
  7. +

    Generate a preliminary DID Log Entry (input JSON array) +The DID log entry is an input JSON array that when completed contains the following items: +[ versionId, versionTime, parameters, DIDDoc State, Data Integrity Proof ]. When creating +(registering) the DID the first entry starts with the follows items for processing: +[ "{SCID}", "<current time>", "parameters": [ <parameters>], { "value": "<DIDDoc with Placeholders>" } ]

    +
      +
    1. Add a preliminary versionId value +The first item in the input JSON array MUST be the placeholder string {SCID}.
    2. +
    3. Add the versionTime value +The second item in the input JSON array MUST be a valid ISO8601 date/time string, +and that the represented time MUST be before or equal to the current time.
    4. +
    5. Define the parameters +The third item in the input JSON array MUST be the parameters +JSON object. The parameters are used to configure the DID generation and verification +processes. All parameters MUST be valid and all required values in the first version +of the DID MUST be present.
    6. +
    +

    The DID Generation and Verification Parameters +section of this specification defines the permitted parameters. That +section defines what items MUST be included in this first log entry for the DID. +Collect and use the specified parameters in the remainder of the DID creation steps.

    +
      +
    1. Add the initial DIDDoc +The fourth item in the input JSON array MUST be the JSON object {"value": <diddoc> }, +where <diddoc> is the initial DIDDoc as described in the previous step 3.
    2. +
    +
  8. +
  9. +

    Update the preliminary DID Log Entry to the initial DID Log Entry +Use the preliminary DID log entry to perform the consecutive steps:

    +
      +
    1. Calculate the SCID +The input JSON array MUST be used to calculate the SCID for the DID as defined in +the SCID Generation and Verification section of this +specification.
    2. +
    3. Replace the placeholder {SCID} +Replace throughout the input JSON array the placeholder “{SCID}” for the SCID with +the calculated SCID from the previous step.
    4. +
    5. Calculate the Entry Hash +The JSON array updated in the previous step MUST be used to calculate the Entry Hash +(entryHash) for the log entry, as defined in the +Entry Hash Generation and Verification section of +this specification.
    6. +
    7. Replace the preliminary versionId value +The value of the versionId (first) item of the JSON array MUST be updated with the +literal string 1- (for version number 1) followed by the entryHash value produced in the previous step.
    8. +
    9. Generate the Data Integrity proof +A Data Integrity proof on the initial DIDDoc MUST be generated +using an authorized key from a DID in the required updateKeys item in the parameters, +and the versionId as the proof challenge.
    10. +
    +

    If the DID Controller has opted to use witnesses for the DID, the required approvals +from the DID’s witnesses MUST be collected and added to the +Data Integrity proof item. See the DID Witnesses section of this specification.

    +
      +
    1. Add the Data Integrity proof +The fifth item in the input JSON array MUST be added to the JSON array. The result is in the +initial DID log entry for the DID.
    2. +
    +
  10. +
  11. +

    Generate the first JSON Line +The DID log entry MUST be updated to be a JSON Lines +entry by removing extraneous white space and appending a carriage return, +and stored as the contents of the file did.jsonl.

    +
  12. +
  13. +

    Publish the DID Log +The complete DID Log file MUST be published at the appropriate Web location defined by +the did:tdw DID identifier (see step 1)

    +
      +
    • This is a logical operation – how a deployment serves the did.jsonl +content is not constrained.
    • +
    • Use the DID-to-HTTPS Transformation +steps to transform the DID into the Web location of the DID Log +file.
    • +
    +
  14. +
+

A controller MAY generate an equivalent did:web DIDDoc and publish it as +defined in the +Publishing a Parallel did:web DID section +of this specification. The did:web DIDDoc could be used for backwards +compatibility as a transition is made from did:web to did:tdw. Verifiers +using the did:web lose the verifiable properties and history of the did:tdw +for the convenience of the simple retrieval of the did:web DIDDoc.

+

§ Read (Resolve)

+

The following steps MUST be executed to resolve the DIDDoc for a did:tdw DID:

+
    +
  1. The DID-to-HTTPS Transformation steps +MUST be used to transform the DID into an HTTPS URL for the DID file.
  2. +
  3. Perform an HTTPS GET request to the URL using an agent that can successfully +negotiate a secure HTTPS connection, which enforces the security requirements +as described in +Security and privacy considerations.
  4. +
  5. When performing the DNS resolution during the HTTPS GET request, the client +SHOULD utilize [RFC8484] in order to prevent tracking of the identity +being resolved.
  6. +
  7. The DID Log file MUST be processed as described below.
  8. +
+

To process the retrieved DID Log file, the resolver MUST carry out +the following steps on each of the log entries in the order they appear in the +file, applying the parameters set from the current and previous +entries. As noted in the DID Log File section, log entries +are each a JSON array with five items:

+
    +
  1. versionId
  2. +
  3. versionTime
  4. +
  5. parameters
  6. +
  7. DIDDoc State – either the full value or a JSON Patch patch +to be applied to the prior version of the DIDDoc.
  8. +
  9. A Data Integrity proof array for the version of the DIDDoc corresponding to that +entry.
  10. +
+

For each entry:

+
    +
  1. Update the currently active parameters with the parameters from +the entry (if any). Continue processing using the now active set of +parameters. +
      +
    • While all parameters in the first Log Entry take effect +immediately, some kinds of parameters defined in later entries only take +effect after that entry has been published. For example, rotating the +authorized keys to update a DID takes effect only after the entry in +which they are defined has been published.
    • +
    +
  2. +
  3. The Data Integrity proof in the entry MUST be valid and signed by +an authorized key as defined in the Authorized Keys +section of this specification. +
      +
    1. If the DID Controller has opted to use witnesses and the +last entry of the log is being processed, the witness Data proofs MUST be valid and MUST be signed by a threshold +of witnesses. For details, see the DID +Witnesses section of this specification.
    2. +
    +
  4. +
  5. Verify the versionId for the entry. Recall the the versionId is the +concatenation of the version number, a dash (-), and the entryHash. +
      +
    1. The version number MUST be 1 for the the first log entry and MUST be +incremented by one for each subsequent log entry.
    2. +
    3. A dash - MUST follow the version number.
    4. +
    5. The entryHash MUST follow the dash, and MUST be verified using +the process defined in the Entry Hash Generation and +Verification section of this +specification.
    6. +
    +
  6. +
  7. The versionTime MUST be a valid ISO8601 date/time string. The +versionTime for each log entry MUST be greater than the +previous entry’s time. The versionTime of the last entry MUST be +earlier than the current time.
  8. +
  9. Parse and apply the did:tdw DID Method configuration parameters. Note +that in versions after the first, some parameters apply to immediately and +impact the process of the current DID version, while others, such as +updateKeys and witnesses apply after the current version has been +published. The parameters MUST adhere to the did:tdw DID Method +Parameters section of this specification.
  10. +
  11. When processing the first DID log entry, verify the SCID +(defined in the parameters) according to the +SCID Generation and Verification section +of this specification.
  12. +
  13. Extract the contents of the DIDDoc for each entry by using the JSON value +of the value item, or by using JSON Patch to apply the JSON +value of the patch entry item to the previous version of the DIDDoc.
  14. +
  15. If Key Pre-Rotation is being used, the hash of all updateKeys entries +in the parameters item MUST match a hash in +the active array of nextKeyHashes parameter, as defined in the +Pre-Rotation[Key Pre-Rotation Hash Generation and Verification](#pre-rotation-key-hash-generation-and-verification) +section of this specification.
  16. +
  17. If any verifications fail, discard the DID as invalid with an error message.
  18. +
  19. As each log entry is processed and verified, collect the following information +about each version: +
      +
    1. The DIDDoc.
    2. +
    3. The versionId of the DIDDoc.
    4. +
    5. The versionTimeof the DIDDoc.
    6. +
    7. The latest list of active multikey formatted public keys +authorized to update the DID, from the updateKeys lists in the +parameters.
    8. +
    9. If pre-rotation is being used, the hashes of authorized DIDs that may +be used in later updateKeys lists. The pre-rotation hashes are in the +nextKeyHashes list in the parameters.
    10. +
    11. All other did:tdw processing configuration settings as defined by in the +parameters object.
    12. +
    +
  20. +
+

On completing the processing and successful verification of all entries in the +DID Log, respond to the DID resolution request, including the +application of DID query parameters such as ?versionId= and ?versionTime= with +the appropriate DIDDoc version and content.

+

The following error codes and descriptions may be returned when resolving a DID.

+
TODO

Document the full list of error codes that can be generated in resolving a DID.

+
+
    +
  • Code 404: The did:tdw DID Log file did.jsonl was not found.
  • +
+
§ Reading did:tdw DID URLs
+

A did:tdw resolver MAY implement the resolution of the /whois and a DID +URL Path using the whois LinkedVP Service and +DID URL Path Resolution Service as defined in +this specification by processing the DID Log and then dereferencing the +DID URL based on the contents of the DIDDoc. The client of a resolver that does +not implement those capabilities must use the resolver to resolve the +appropriate DIDDoc, and then process the resulting DID URLs themselves. Since +the default DID-to-HTTPS URL transformation is trivial, did:tdw +DID Controllers are strongly encouraged to use the default behavior +for DID URL Path resolution.

+

§ Update (Rotate)

+

To update a DID, a new, verifiable DID Log Entry must be generated, +witnessed (if necessary), appended to the existing DID Log (did.jsonl), +and published to the web location defined by the DID. The process to generate a +verifiable DID Log Entry follows a similar process to the +Create process, as follows:

+
    +
  1. Make the desired changes to the DIDDoc. While the contents of a new DIDDoc +version are (mostly) up to the DID controller, there are some limitations: +
      +
    1. If the DID is configured to support portability, the root id +item in the DIDDoc MAY be changed when the DID Controller wants to (or +is forced to) publish the DID at a different Internet location and wants +to retain the SCID and history of the DID. For details, see the +DID Portability section of this specification.
    2. +
    +
  2. +
  3. Define a JSON array of parameters that affect the evolution of the +DID. The parameters MUST be from those listed in the did:tdw DID +Method Parameters section of this +specification. Any parameters defined in the array override the +previously active value, while any parameters not included imply the +existing values remain in effect. If no changes to the parameters +are needed, an empty JSON object {} MUST be used. +
      +
    • While all parameters in the first Log Entry take effect +immediately, some types of parameters defined in later entries only take +effect after the entry has been published. For example, rotating the keys +authorized to update a DID or changing the witnesses for a DID take effect +only after the entry in which they are defined has been published.
    • +
    +
  4. +
  5. Generate a preliminary DID Log Entry JSON array with the following JSON items: +
      +
    1. The versionId MUST be versionId value from the previous DID Log Entry.
    2. +
    3. The versionTime value MUST be an ISO8601 format time. The time +MUST be greater than the time of the previous log entry, and MUST be less +than or equal to the current time.
    4. +
    5. The parameters passed in as a JSON object.
    6. +
    7. Generate a JSON Patch to evolve the previous DIDDoc version to +the new DIDDoc version, and put the resulting patch in the item as +{"patch": <DIDDoc Patch>}. For details of the process, see the +Generating and Applying a JSON Patch +section of this specification. +
        +
      1. An implementation MAY skip the JSON Patch process and +simply put the full new version of the DIDDoc in the item +{"value": <DIDDoc>} as is done in the initial entry in the log.
      2. +
      +
    8. +
    +
  6. +
  7. Calculate the new versionId of the new DID Log Entry, including +incrementing the version number integer and using the process described in +the Entry Hash Generation and Verification +section of this specification.
  8. +
  9. Replace the value of the versionId item in the preliminary DID Log with the value produced in the previous step.
  10. +
  11. Generate a Data Integrity proof on the new DIDDoc of the entry +using an authorized key, and the versionId as the proof +challenge. The definition of “authorized” is formalized in the +Authorized Keys section of this specification.
  12. +
  13. If the DID Controller has opted to use witnesses for the +DID, collect the required approvals from the DID’s witnesses, adding +their proofs to the data integrity proof. See the DID +Witnesses section of this specification.
  14. +
  15. The proof array MUST be added as the fifth and last JSON item in the log entry.
  16. +
  17. The entry MUST be made a JSON Line by removing extra whitespace, adding a \n +to the entry.
  18. +
  19. The new log entry MUST be appended to the existing contents of +the DID Log file did.jsonl.
  20. +
  21. The updated DID Log file MUST be published the appropriate +location defined by the did:tdw identifier. +
      +
    • This is a logical operation – how a deployment serves the did.jsonl +content is not constrained.
    • +
    +
  22. +
+

A controller MAY generate an equivalent, updated did:web DIDDoc and +publish it as defined in the +Publishing a Parallel did:web DID +section of this specification.

+

§ Deactivate (Revoke)

+

To deactivate the DID, the DID Controller SHOULD add to the DID log entry parameters the item "deactivated": true. A DID MAY update the DIDDoc further to indicate the deactivation of +the DID, such as including an empty updateKeys list ("updateKeys": []) in +the parameters, preventing further versions of the DID.

+

A resolver encountering in the DID log entry parameters the +item "deactivated": true MUST return in the DIDDoc Metadata the JSON item +"deactivated": true, as per the [[spec:DID-RESOLUTION]] specification.

+

§ DID Method Processes

+

The DID Method Operations reference several processes +that are executed during DIDDoc generation and DID resolution verification. Each +of those processes is specified in the following sections.

+

§ did:tdw DID Method Parameters

+

Entries in the did:tdw DID Log file contain, in the 3rd item, a JSON +object that defines the DID processing parameters being used by the DID when publishing that and subsequent DID log entries. A DID Resolver +will use the same parameters when processing the DID Log to resolve the +DID. The parameters object MUST include only the items defined in this +specification.

+
EXAMPLE

An example of the JSON prettified parameters item in the first DID Log entry for a DID:

+
{
+    "prerotation": true,
+    "portable": false,
+    "updateKeys": [
+      "z82LkqR25TU88tztBEiFydNf4fUPn8oWBANckcmuqgonz9TAbK9a7WGQ5dm7jyqyRMpaRAe"
+    ],
+    "nextKeyHashes": [
+      "enkkrohe5ccxyc7zghic6qux5inyzthg2tqka4b57kvtorysc3aa"
+    ],
+    "method": "did:tdw:0.3",
+    "scid": "{SCID}"
+}
+
+
+

The allowed parameter items and (where applicable) enumerated values for those +items are defined below.

+
    +
  • method: Defines the did:tdw specification version to use when processing a +given DID’s log file. As new versions of this specifications are +defined, additional parameters and enumerated values will be added to this. This +allows a long lasting DID to evolve the settings being used by the DID over time, +such as changing the hash algorithm used, or the Data Integrity cryptosuite. +
      +
    • This item MUST appear in the first DID log entry.
    • +
    • This item MAY appear in later DID log entries to indicate that +the processing rules for that and later entries have been changed to a +different specification version.
    • +
    • Acceptable values for this specification are: +
        +
      • did:tdw:0.3: Requires that the rules defined in this specification be used +in processing the log. Implied by the value are the following: + +
      • +
      +
    • +
    +
  • +
  • scid: The value of the SCID for this DID. + +
  • +
  • updateKeys: A list of one or more multikey formatted public keys +associated with the private keys that are authorized to sign the log entries +that update the DID from one version to the next. An instance of the list in +an entry replaces the previously active list. If an entry does not have the +updateKeys item, the currently active list continues to apply. See the +Authorized Keys section of this specification for +additional details. +
      +
    • This item MUST appear in the first DID log entry.
    • +
    • A key from the updateKeys item in the first DID log entry +MUST be used to authorize the initial log entry. In all other +DID log entries, an updateKeys item becomes active after the +publication of its entry – meaning its log entry MUST be +signed by a key the most recent updateKeys list from a prior DID log entry.
    • +
    +
  • +
  • portable: A boolean (true / false) indicating if the DID is portable and +thus can be renamed to change the Web location of the DID. +
      +
    • The value can ONLY be set to true in the first log entry, the initial version of the DID.
    • +
    • If not explicitly set in the first log entry, it is set to false.
    • +
    • Once the value has been set to false, it cannot be set back to true.
    • +
    • See the section of this specification on DID Portability +for more details about renaming a did:tdw DID.
    • +
    +
  • +
  • prerotation: A boolean value indicating that subsequent authentication keys +added to the DIDDoc (after this version) MUST have their hash included in +a nextKeyHashes parameter item. +
      +
    • The value is initialized to false until the item is included in a +DID log entry.
    • +
    • Once the value is set to true in a DID log entry it MUST NOT +be set to false in a subsequent entry.
    • +
    +
  • +
  • nextKeyHashes: An array of strings that are hashes of multikey +formatted public keys that MAY be added to the updateKeys list in the +log entry of a future version of the DID. +
      +
    • The process for generating the hashes and additional details for using pre-rotation are defined in the +Pre-Rotation Key Hash Generation and Verification +section of this specification.
    • +
    • If the parameter prerotation has been set to true, all multikey +formatted public keys added in a new updateKeys list MUST have their +hashes listed in the currently active nextKeyHashes list.
    • +
    • A DID Controller MAY put extra strings in the nextKeyHashes +item that are not subsequently used in an updateKeys entry.
    • +
    • When prerotation is active and the updateKeys parameter is included in a +parameters item, a nextKeyHashes item with a new set of hashes +MUST be included in the same parameters item. Any unused +hashes in the prior nextKeyHashes are ignored.
    • +
    +
  • +
  • witness: A JSON object containing the parameters for declaring the witnesses +for the DID, and the parameters for the process of updating a DID via a +collaboration with witnesses prior to publication. For details of +this item data and its usage in the approvals process, see the +DID Witnesses section of this specification. +
      +
    • A witness item in the first DID log entry is used to define the +witnesses and necessary threshold for that initial log entry. In all other +DID log entries, a witness item becomes active after the publication +of its entry – meaning its log entry MUST be witnessed by the most recent +witnesses from a prior DID log entry.
    • +
    +
  • +
  • deactivated: A JSON boolean that SHOULD be set to true when the DID is to +be deactivated. See the deactivate (revoke) section of +this specification for more details.
  • +
  • ttl: A number, the number of seconds that a cache entry for a resolved +did:tdw DID SHOULD last, as recommended by the DID Controller. A +resolver can use this value in deciding whether to retrieve a new version of +the DID’s did.jsonl file. If not specified, resolvers MAY set a default +based on the business needs of the resolver clients. +
      +
    • Caching a did:tdw can be valuable in places where the business rules +require resolving a number of DID URLs for the same DID. For example, a +client might want call the resolver to the current DIDDoc, and then make +repeated calls to get all of the previous versions of the DIDDoc. By caching +the DIDDoc state, the resolver would not have to retrieve and process the +DID Log on each call.
    • +
    • A Web Server handling one or more did.jsonl files MAY be configured to +use a comparable HTTP TTL per [RFC9111].
    • +
    +
  • +
+

§ SCID Generation and Verification

+

The self-certifying identifier or SCID is a required parameter in the +first DID log entry and is the hash of the DID’s inception event.

+
§ Generate SCID
+

To generate the required SCID for a did:tdw DID, the DID Controller +MUST execute the following function:

+

base58btc(multihash(JCS(preliminary log entry with placeholders), <hash algorithm>))

+

Where:

+
    +
  1. +

    The preliminary [[ref: log entry]] with placeholders consists of the following +pre-publication JSON array of what will become the first log entry. The +placeholder is the literal string “{SCID}”.

    +
      +
    • The versionId entry, which MUST be {SCID}.
    • +
    • The versionTime entry, which MUST be a string that is the current time in +ISO8601 format, e.g., "2024-04-05T07:32:58Z"
    • +
    • The complete parameters for the initial log entry as defined by the +DID Controller, with the placeholder wherever the SCID will +eventually be placed.
    • +
    • The {"value": <DIDDoc>} element with placeholders wherever the SCID will +eventually be placed in the DIDDoc.
    • +
    +
  2. +
  3. +

    JCS is an implementation of the JSON Canonicalization Scheme +[RFC8785]. It outputs a canonicalized representation of its JSON +input.

    +
  4. +
  5. +

    multihash is an implementation of the multihash specification. Its +output is a hash of the input using the associated <hash algorithm>, +prefixed with a hash algorithm identifier and the hash size.

    +
  6. +
  7. +

    <hash algorithm> is the hash algorithm used by the DID Controller. +The hash algorithm MUST be one listed in the +parameters defined by the version of the +did:tdw specification being used by the DID Controller.

    +
  8. +
  9. +

    base58btc is an implementation of the base58btc function. +Its output is the base58 encoded string of its input.

    +
  10. +
+
§ Verify SCID
+

To verify the SCID of a did:tdw DID being resolved, the resolver +MUST execute the following process:

+
    +
  1. Extract the first DID log entry and use it for the rest of the steps +in this process.
  2. +
  3. Extract the scid item value from the parameters in the DID log entry.
  4. +
  5. Determine the hash algorithm used by the DID Controller from the multihash scid value. +
      +
    • The hash algorithm MUST be one listed in the +parameters defined by the version of the +did:tdw specification being used by the DID Controller based on the +method parameters item.
    • +
    +
  6. +
  7. Remove the data integrity proof item from the first DID log entry.
  8. +
  9. Replace the versionId item’s value with the literal "{SCID}".
  10. +
  11. Treat the resulting log entry as a string and do a text replacement of the scid +value from Step 2 with the literal string {SCID}.
  12. +
  13. Use the result and the hash algorithm (from Step 3) as input to the function +defined in the Generate SCID section (above).
  14. +
  15. The output string MUST match the scid extracted +in Step 2. If not, terminate the resolution process with an error.
  16. +
+

§ Entry Hash Generation and Verification

+

The entryHash follows the version number and dash character - in the +versionId item in each DID log entry. Each entryHash is calculated +across its log entry, excluding the Data Integrity proof. The +versionId used in the input to the hash is a predecessor value to the current +log entry, ensuring that the entries are cryptographically “chained” +together in a microledger. For the first log entry, the predecessor +versionId is the SCID (itself a hash), while for all other entries it is the +versionId item from the previous log entry.

+
§ Generate Entry Hash
+

To generate the required hash for a did:tdw log entry, the DID Controller +MUST execute the process base58btc(multihash(JCS(entry), <hash algorithm>)) given a +preliminary log entry as the string entry, where:

+
    +
  1. JCS is an implementation of the JSON Canonicalization Scheme +([RFC8785]). Its output is a canonicalized representation of its +input.
  2. +
  3. multihash is an implementation of the multihash specification. Its +output is a hash of the input using the associated <hash algorithm>, +prefixed with a hash algorithm identifier and the hash size.
  4. +
  5. <hash algorithm> is the hash algorithm used by the DID Controller. +The hash algorithm MUST be one listed in the +parameters defined by the version of the +did:tdw specification being used by the DID Controller.
  6. +
  7. base58btc is an implementation of the base58btc function. +Its output is the base58 encoded string of its input.
  8. +
+

The following is an example of a preliminary log entry that is processed to +produce an entry hash. As this is a first entry in a DID Log, the input +entryHash (first item) is the SCID of the DID.

+
["Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu", "2024-07-29T17:00:27Z", {"prerotation": true, "updateKeys": ["z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc"], "nextKeyHashes": ["QmcbM5bppyT4yyaL35TQQJ2XdSrSNAhH5t6f4ZcuyR4VSv"], "method": "did:tdw:0.3", "scid": "Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu"}, {"value": {"@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/multikey/v1"], "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example"}}]
+
+

Resulting entry hash: QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ

+
§ Verify The Entry Hash
+

To verify the entryHash for a given did:tdw DID log entry, a DID +Resolver MUST execute the following process:

+
    +
  1. Extract the versionId (first item) in the DID log entry, and +remove from it the version number and dash prefix, leaving the log entry +entryHash.
  2. +
  3. Determine the hash algorithm used by the DID Controller from the multihash entryHash value. +
      +
    • The hash algorithm MUST be one listed in the +parameters defined by the version of the +did:tdw specification being used by the DID Controller based on the +method parameters item set in the current or most recent prior log entry.
    • +
    +
  4. +
  5. Remove the Data Integrity proof (5th item) from the log entry.
  6. +
  7. Set the first item of the entry to the versionId (first item) of the +previous log entry. If this is the first entry in the log, set the value to +the <scid>, the SCID of the DID.
  8. +
  9. Calculate the hash string as base58btc(multihash(JCS(entry), <hash algorithm>)), where: +
      +
    1. entry is the data from the previous step.
    2. +
    3. JCS is an implementation of the JSON Canonicalization Scheme +([RFC8785]). Its output is a canonicalized representation of its +input.
    4. +
    5. multihash is an implementation of the multihash specification. +Its output is a hash of the input using the associated <hash algorithm>, +prefixed with a hash algorithm identifier and the hash size.
    6. +
    7. <hash algorithm> is the hash algorithm from Step 2.
    8. +
    9. base58btc is an implementation of the base58btc function. +Its output is the base58 encoded string of its input.
    10. +
    +
  10. +
  11. Verify that the calculated value matches the extracted entryHash value from +Step 1. If not, terminate the resolution process with an error.
  12. +
+

§ Authorized Keys

+

Each entry in the DID Log MUST include a Data Integrity +proof signed by a key authorized to control (create, update, deactivate) the +DID. The authorized verification keys for did:tdw are the multikey-formatted +public keys in the active updateKeys list from the parameters item of +the log entries. Any of the authorized verification keys may be referenced +in the Data Integrity proof.

+

For the first log entry the active updateKeys list is the one in +that first log entry. For all subsequent entries, the active list +is the most recent updateKeys before the log entry to be verified. Thus, +the general case is that each log entry is signed by the keys from the +previous log entry. Once a log entry containing an updateKeys list is +published, that updateKeys becomes the active list, and the previous +updateKeys are ignored.

+

A resolver of the DID MUST verify the signature and that the key used for +signing each DID Log entry is one from the list of active updateKeys. +If not, terminate the resolution process with an error.

+

The did:tdw Implementation Guide contains further discussion on the management +of keys authorized to update the DID.

+

§ Generating and Applying a JSON Patch

+

Each time a new did:tdw version is created, the DID Controller +MAY generate a JSON Patch to concisely define the changes in the +DIDDoc from the previous version. A DID log entry that uses JSON Patch +has a JSON object with a patch property, with the value the JSON Patch as its DIDDoc State (fourth) item. A DID Controller MAY set the +DIDDoc State item of a DID log entry to be the JSON item value, with its +value the complete DIDDoc. Typically (but not required), a DID Controller +will use value for the first DID log entry and patch for all +subsequent entries.

+

To create the value for a patch item for a DID log entry, the DID Controller MUST:

+
    +
  1. Have the fully resolved previous version of the DIDDoc.
  2. +
  3. Have the updated new version of the DIDDoc to be added.
  4. +
  5. Execute an implementation of JSON Patch that takes the two DIDDocs +as inputs (previous before, new after) and outputs the resulting JSON Patch +from before to after.
  6. +
  7. Set the DIDDoc State (fourth) item of the DID log entry to {"patch": "<patch>"}, +where <patch> is the output of the previous step.
  8. +
+

When processing a DID log entry with a patch as the fourth item, a +resolver MUST:

+
    +
  1. Have the fully resolved previous version of the DIDDoc.
  2. +
  3. Extract the value of the DIDDoc State (fourth) item of the DID log entry patch value. +
      +
    1. If the DIDDoc State item is value, its value is the DIDDoc, and the +next step is not needed.
    2. +
    +
  4. +
  5. Execute an implementation of JSON Patch that takes the previous +DIDDoc and the extracted patch value as inputs, and outputs the +resulting new version of the DIDDoc.
  6. +
+

The output is the DIDDoc for that version of the DID.

+

§ DID Portability

+

As noted in the Update (rotate) section of the specification, +a did:tdw DID can be renamed by changing the id DID string in the +DIDDoc to one that resolves to a different HTTPS URL if the following conditions are met.

+
    +
  • The DID Log of the renamed DID MUST contain all of the log from the creation of the DID.
  • +
  • The log entry in which the DID is renamed MUST be a valid DID entry +building on the prior DID log entries, per this specification.
  • +
  • The parameter portable MUST be set to true, as defined in the +DID Method Parameters section.
  • +
  • The SCID MUST be the same in the original and renamed DID.
  • +
  • The DIDDoc MUST contain the prior DID string as an alsoKnownAs entry.
  • +
+

§ Pre-Rotation Key Hash Generation and Verification

+

Pre-rotation requires a DID Controller to commit to the authorization +keys that will later be used (“rotated to”) for updating the DIDDoc. The purpose +of committing to future keys is that if the currently authorized keys are +compromised by an attacker, the attacker should not be able to take control of +the DID by using the compromised keys to rotate to new keys the attacker +controls. Assuming the attacker has not also compromised the committed key +pairs, they cannot rotate the authorization keys without detection. See the +non-normative section about Pre-Rotation[Using Pre-Rotation Keys](#using-pre-rotation-keys) +in the Implementer’s Guide for additional guidance.

+

As described in the parameters +section of this specification, a DID Controller MAY define that +prerotation is active for the DID (value true). When pre-rotation is active, +all verification multikeys in the updateKeys parameters item in other +than the initial version of the DIDDoc MUST have their hash in the currently +active nextKeyHashes` arrays from a previous DID log entry. If +not, terminate the resolution process with an error.

+

To create a hash to be included in the nextKeyHashes array, the DID MUST execute the following process for each possible future +authorization key.

+
    +
  1. Generate a new key pair.
  2. +
  3. Generate a multikeys representation of the public key of the new key +pair.
  4. +
  5. Calculate the hash string as base58btc(multihash(multikey)), where: +
      +
    1. multikey is the multikey representation of the public key from Step 2.
    2. +
    3. multihash is an implementation of the multihash specification. +Its output is a hash of the input using the associated <hash algorithm>, +prefixed with a hash algorithm identifier and the hash size.
    4. +
    5. <hash algorithm> is the hash algorithm used by the DID Controller. +The hash algorithm MUST be one listed in the +parameters defined by the version of the +did:tdw specification being used by the DID Controller.
    6. +
    7. base58btc is an implementation of the base58btc function. +Its output is the base58 encoded string of its input.
    8. +
    +
  6. +
  7. Insert the calculated hash into the nextKeyHashes array being built up within +the parameters item.
  8. +
  9. The generated key pair SHOULD be safely stored so that it can be used in +a later DID version to become a DID authorization key. At that time, the +multikey representation of the public key will be inserted into the +updateKeys item in the parameters. After that log entry is +published, the private key can be used to sign DID update authorizations +proofs.
  10. +
+

A DID Controller MAY add extra hashes (for keys or just random +strings) into a nextKeyHashes array.

+

When processing other than the first DID log entry where the +prerotation parameter is active, a did:tdw resolver MUST:

+
    +
  1. For each multikey in the updateKeys item in the parameters of +the log entry, calculate the hash and hash algorithm for the mulithash multikey.
  2. +
  3. The hash algorithm MUST be one listed in the +parameters defined by the version of the +did:tdw specification being used by the DID Controller.
  4. +
  5. The resultant hash MUST in the most recently set nextKeyHashes prior to +the log entry being processed. If not, terminate the resolution +process with an error.
  6. +
  7. A new nextKeyHashes list MUST be in the parameters of the log currently being processed. If not, terminate the resolution process with +an error.
  8. +
+

§ DID Witnesses

+

The witness process for a DID provides a way for other collaborators to +work with the DID Controller to “witness” the publication of a new version of +the DID. Including witnesses can prevent malicious updates to the DID by both +the DID Controller and external parties. This specification defines +the mechanism for using witnesses but leaves the governance and policy +questions about when and how to use the mechanism to implementers.

+

Witnesses can prevent a DID Controller from updating/removing DID versions of a +DID without detection. Witnesses are also a further mitigation against malicious +actors compromising both a DID Controller's authorization key(s) to update the +DID, and the DID Controller's web site where the DID log is published. +With both compromises, a malicious actor could take control over the DID by +rewriting the DID Log using the keys they have comprised. By adding +witnesses that monitor and approve each version update, a malicious +actor cannot rewrite the previous history without also compromising a sufficient +number of witnesses.

+

An overview of the witness mechanism is as follows:

+
    +
  • The DID Controller specifies (in the parameters of a log) a list of witnesses, DIDs that together with the DID will contribute to “approving” all subsequent versions of the +DID. +
      +
    • Ideally, the DID Controller does that in the inception event for the +DID.
    • +
    • Over time, the list of witnesses may evolve, with each change being +approved by the declared list of witnesses from before such a +change.
    • +
    +
  • +
  • The DID Controller prepares a DID Log Entry and shares it with +the witnesses. +
      +
    • The specification leaves to implementers how the log entry data is provided to the witnesses.
    • +
    +
  • +
  • Each witness verifies the DID Log Entry, as defined by this +specification. If not, the witnesses MUST NOT approve the log entry. + +
  • +
  • Each witness determines (based on the governance of the ecosystem) +if they approve of the DID version update. +
      +
    • This specification has no opinion on what “approve” means for any +deployment of did:tdw. That is up to the ecosystem in which the DID and witnesses are participating.
    • +
    +
  • +
  • If the verification is successful and the approval granted, the witness sends a Data Integrity proof to the DID Controller similar +to that generated by the DID Controller, with the DIDDoc as the signed object, +the entry log’s versionId as the challenge, but signed by the witnesses key.
  • +
  • When a weighted threshold of proofs are received, the DID Controller +inserts the witnesses's proofs into the array of proofs that are the last item in +the DID Log Entry and publishes the updated version of the DID. +
      +
    • In publishing a new version of the DID Log, the DID SHOULD remove the witness Data Integrity proofs from +earlier entries to reduce the size of the log. Only the set of approval +proofs on the last log entry are needed because of the chaining of the +proofs via the use of the entryHash challenge.
    • +
    • Removing the prior entry witness proofs does not affect the verifiability of +the DID because the entryHash calculation does not include the proofs item.
    • +
    • The specification leaves to implementers how the proofs are conveyed to +the DID Controller.
    • +
    +
  • +
+

::: to do

+

To Do: Update to use a Data Integrity Proof Set, where the authorized key identifies +the proof, and the witnesses proofs reference the identifier.

+

:::

+

As with the handling of the updateKeys, DID Log Entry changes require +proofs from the the witnesses active prior to the publication of a +new version. If a new version changes the list of witnesses, that +change must be approved by the prior witnesses. For the first entry +in the DID Log, the witnesses listed in that entry must +approve the version, since there are no “prior” witnesses.

+

The data object for the witness parameters item is as follows. +The threshold design borrows from the verifiable conditions +specification.

+
"witness" : {
+  "threshold": n,
+  "selfWeight": n,
+  "witnesses" : [
+      {
+         "id": "<DID of witness>",
+         "weight": n
+      }
+   ]
+}
+
+

where:

+
    +
  • threshold: an integer that must be attained or surpassed by the sum of the witnesses and +DID Controller's weights for a DID log entry to be considered approved.
  • +
  • selfWeight: an integer that is the weight given the DID Controller's +verified proof, in determining if the threshold has been surpassed.
  • +
  • witnesses: an array of witnesses +
      +
    • id: the DID of the witness
    • +
    • weight: the weight of this witness's approval
    • +
    +
  • +
+

The use of the threshold and weighted approvals (versus needing approvals from +all witnesses) is to prevent faulty witnesses from blocking the publishing of +a new version of the DID. To determine if the threshold has been passed, sum the +weight integer of the received approvals, plus the selfWeight of the DID, and if it equal to or more than threshold, the update can be +published. The calculation MUST also be executed by resolvers processing a +DID Log. For example, if there are three witnesses, each with a weight of 1, +the DID Controller with a selfWeight of 2, and a threshold of 4, the +threshold will be met by two witnesses approving the change, plus the DID.

+

See the Implementer’s Guide section on Witnesses for more +discussion on the witness capability and using it in production scenarios.

+

§ Publishing a Parallel did:web DID

+

Each time a did:tdw version is created, the DID Controller MAY +generate a corresponding did:web to publish along with the did:tdw. To do +so, the DID Controller MUST:

+
    +
  1. Start with the resolved version of the DIDDoc from did:tdw.
  2. +
  3. Execute a text replacement across the DIDDoc of did:tdw:<SCID>: to +did:web:, where <scid> is the actual did:tdw SCID.
  4. +
  5. Add to the DIDDoc alsoKnownAs array, the full did:tdw DID. If the +alsoKnownAs array does not exist in the DIDDoc, it MUST be added.
  6. +
  7. Publish the resulting DIDDoc as the file did.json at the web location +determined by the specified did:web DID-to-HTTPS transformation.
  8. +
+

The benefit of doing this is that resolvers that have not been updated to +support did:tdw can continue to resolve the DID Controller's DIDs. +did:web resolvers that are aware of did:tdw features can use that knowledge, +and the existence of the alsoKnownAs did:tdw data in the DIDDoc to get the +verifiable history of the DID.

+

The risk of publishing the did:web in parallel with the did:tdw is that the +added security and convenience of using did:tdw are lost.

+

§ DID URL Resolution

+

The did:tdw DID Method embraces the power and usefulness of DID URLs, along +with the semantic simplicity of using them with a web-based DID method. +Specifically, a did:tdw implementation MUST:

+
    +
  • Resolve the /whois DID URL path using a [[spec:LINKED-VP]] service, whether +or not it exists in the did:tdw DIDDoc, returning a Verifiable, if published by the DID Controller, found at the same +path as the did.jsonl file, using the /whois.vp filename component, and +the `application/vp’ media type, as per the IANA Verifiable Presentation +Assignment. +
      +
    • For example, did:tdw:{SCID}.example.com/whois returns the verifiable from https://{SCID}.example.com/.well-known/whois.vp.
    • +
    +
  • +
  • Resolve any did:tdw DID URL using a [DID-CORE] relativeRef DID +parameter, whether or not a supporting service exists in the did:tdw DIDDoc, +returning the file found at web location corresponding to the DID-to-HTTPS +transformation. +
      +
    • For example, resolving did:tdw:example.com:{SCID}/governance/issuers.json returns +the file https://example.com/{SCID}/governance/issuer.json
    • +
    • When the {SCID} is placed as a subdomain, the file is found relative to +that subdomain, and not in the .well-known folder where the did.jsonl +file is found. For example, resolving +did:tdw:{SCID}.example.com/governance/issuers.json returns the file +https://{SCID}.example.com/governance/issuer.json.
    • +
    +
  • +
+

In both cases, a DID Controller MAY define services in the DIDDoc +that override the default services that MUST be resolved by the did:tdw +DID Method.

+

The sections below formalize the services that exist by default in did:tdw and +how a DID Controller can override them.

+

§ whois LinkedVP Service

+

The #whois service enables those that receive a did:tdw DID to retrieve and +a Verifiable Presentation (and embedded Verifiable) the DID Controller has decided to publish about itself. +The intention is that anyone wanting to learn more about a particular did:tdw +DID can resolve the <did>/whois DID URL to retrieve a Verifiable published by the DID Controller that contains Verifiable Credentials with the DID as the subject. The DID Controller +includes in the Verifiable Presentation any Verifiable Credentials that it +thinks might be helpful for resolvers in making a trust decision about the DID.

+

It is up to the DID Controller to decide to publish a whois +verifiable presentation, and which verifiable credentials to put into the +verifiable presentation. It is up to a DID resolver to decide what attestations +from third parties are useful in making a trust decision about the DID.

+

did:tdw DIDs automatically supports a /whois service endpoint with the +following definition based on the [[spec:LINKED-VP]] specification, with the +serviceEndpoint defining a similar did:tdw DID-to-HTTPS DID Log +transformation with did.jsonl changed to whois.vp. Differing from the +DID-to-HTTPS transformation is that the +.well-known/ component of the did.jsonl transformation is dropped from the +whois.vp resolution.

+
{
+   "@context": "https://identity.foundation/linked-vp/contexts/v1",
+   "id": "#whois",
+   "type": "LinkedVerifiablePresentation",
+   "serviceEndpoint": "<did-to-https-translation>/whois.vp"
+}
+
+

The returned whois.vp MUST contain a W3C VCDM verifiable signed by the DID and containing verifiable credentials +that MUST have the DID as the credentialSubject.

+

A DID Controller MAY explicitly add to their DIDDoc a did:tdw +service with the "id": "#whois". Such an entry MUST override the implicit +service above. If the DID Controller wants to publish the whois +verifiable presentation in a different format than the W3C format, they MUST explicitly add to their DIDDoc a service with the +"id": "#whois" to specify the name and implied format of the verifiable.

+

To resolve the DID URL <did:tdw DID>/whois, the resolver MUST:

+
    +
  1. Resolve the given did:tdw DID by retrieving, processing, and verifying the +DID log for the did:tdw as defined in this specification.
  2. +
  3. Find the DIDDoc service with the id #whois, if any, or use the implicit +service (above).
  4. +
  5. Resolve the serviceEndpoint URL, if possible, and return the document +found. +
      +
    1. If the serviceEndpoint URL can’t be resolved by the resolver (such as if +the URL protocol is not supported by the resolver), the error Error XXX: YYY MUST be returned.
    2. +
    3. If the file at the defined serviceEndpoint is not found, Error 404: Not Found MUST be returned.
    4. +
    +
  6. +
+

§ DID URL Path Resolution Service

+

The automatic resolution of did:tdw DID URL paths follows the +[DID-CORE] relativeRef specification, as follows:

+
    +
  • a DID path, such as example 2 in section 3.2 DID URL +Syntax gives the example: +did:example:123456/resume.pdf
  • +
  • In turn, that can be treated as the following, as shown in example 8 in the +same section: did:example:123456?service=files&relativeRef=/resume.pdf
  • +
  • The #files service defined below then defines the serviceEndpoint for the +relativeRef. +
      +
    • For did:tdw, that service is implicitly defined, with the +serviceEndpoint matching the did:tdw DID-to-HTTPS +transformation and did.jsonl replaced +by the DID URL Path. If .well-known/ is part of the HTTPS URL, it is +removed from the URL before resolving the URL.
    • +
    +
  • +
+

Thus, the implicit service for DID did:tdw:example.com:dids:<scid> is:

+
{
+   "id": "#files",
+   "type": "relativeRef",
+   "serviceEndpoint": "https://example.com/dids/<scid>"
+}
+
+

A DID Controller MAY explicitly add to their DIDDoc a service with +the "id": "#files". Such an entry MUST override the implicit service +defined above.

+

To resolve the DID URL <did:tdw DID>/path/to/file, the resolver MUST:

+
    +
  1. Resolve the given did:tdw DID by retrieving, processing, and verifying the +DID log for the did:tdw as defined in this specification.
  2. +
  3. Find the DIDDoc service with the id #files, if any, or use the implicit +service (above).
  4. +
  5. Resolve the serviceEndpoint URL with the DID URL Path appended, if +possible, and return the document found at that location. +
      +
    1. If the serviceEndpoint URL can’t be resolved by the resolver (such as if +the URL protocol is not supported by the resolver), the error Error XXX: YYY MUST be returned.
    2. +
    3. If the file at the path appended to the defined serviceEndpoint is not +found, the error Error 404: Not Found MUST be returned.
    4. +
    +
  6. +
+

§ Security and Privacy Considerations

+

§ DNS Considerations

+

§ DNS Security Considerations

+

Implementers must secure DNS resolution to protect against attacks like Man in +the Middle, following the detailed guidance in the did:web +specification. +The use of DNSSEC [RFC4033], [RFC4034], [RFC4035] is +essential to prevent spoofing and ensure authenticity of DNS records.

+

§ DNS Privacy Considerations

+

Resolving a did:tdw identifier can expose users to tracking by DNS providers +and web servers. To mitigate this risk, it’s recommended to use privacy-enhancing +technologies such as VPNs, TOR, or trusted universal resolver services, in line +with strategies outlined in the did:web +specification +including emerging RFCs such as Oblivious DNS over +HTTPS +for DNS privacy.

+

§ In-transit Security

+

For in-transit security, the guidance provided in the did:web +specification +regarding the encryption of traffic between the server and client should be +followed.

+

§ International Domain Names

+

[DID-CORE] identifier syntax does not allow Unicode in method name nor +method specific identifiers.

+

Implementers should be cautious when implementing support for DID URLs that rely +on domain names or path components that contain Unicode characters.

+

See also:

+ +

§ Implementors Guide

+

§ Implementations

+

Proof of concept implementations of did:tdw software for DID Controllers and resolvers can be found here:

+ +

Both currently (as of 2024.04.11) support all of the features of the core did:tdw including Key Pre-Rotation. Not yet supported is the the concept of witnesses.

+

§ Using Pre-Rotation Keys

+

In an effort to prevent the loss of control over a decentralized identifier +(DID) due to a compromised private key, pre-rotation keys are +introduced. These commitments, made by the DID Controller, are +declarations about the keys that will be published in future versions of the DID +document, without revealing the keys themselves.

+

The primary goal of pre-rotation keys is to ensure that even if an attacker +gains access to the current active key, they will not be able to take control of +the DID. This safeguard is achieved because the attacker could not simply rotate to +a key they generate and control. Rather, they would need to have also +compromised the unpublished (and presumably securely stored) pre-rotation key in +order to rotate the DID keys.

+

The cost of having pre-rotation protection is a much more complicated process to update +the keys of a DID. The following are some considerations we have come across in +considering how to use the pre-rotation feature. The feature definitely adds a +layer of key management complexity in return for the benefit.

+

§ Key Rotation with Pre-Rotation

+

In using pre-rotation, a DID Controller should generate an “active” key +for the DIDDoc where it can be used for “production” purposes (signing, +decrypting), and generates the “next key” in an isolated location from +production. This prevents both the “active” and “next key” from being compromised in the +same attack. For example, an intruder gets into your infrastructure and is able to extract all of your +private keys both DID control keys would be lost. Thus, we expect the feature to be used as follows:

+
    +
  • The DID Controller creating the DID would request from an isolated +service the hash of the “next key” as defined in this specification. For +example, an entity might have the “active” DID/key hosted by one Cloud +Provider, and the “next key” by another, on the theory that an attacker might +get into one environment or another but not both.
  • +
  • When a key rotation is to be done, two entries are put in the log, using the following steps by the DID Controller: +
      +
    1. Get the full key reference entry from the isolated service for the pre-rotation “nextKey”.
    2. +
    3. Locally generate a pre-rotation key hash for a new key that will soon become the “active” key.
    4. +
    5. Add a DID log entry that includes the items from the previous two steps, and signs the proof using an authorized key (that presumably it controls, though not required).
    6. +
    7. Although the DID log could be published now, it is probably best to hold off and publish it after adding a second, as described by the rest of the steps.
    8. +
    9. Get a new pre-rotation hash from the isolated service.
    10. +
    11. Get the full key-rotation key reference for the pre-rotation hash created for the last DID log entry.
    12. +
    13. Add a DID Log entry that includes the items from the previous two step
    14. +
    15. If the key rotated in the previous DID log entry was a/the +authorized key to make updates to the DID, call the isolated service to produce +the Data Integrity proof over the entry using the key the isolated +service controls. +
        +
      1. This step is not needed if the active service has a key authorized to sign the DIDDoc update.
      2. +
      +
    16. +
    17. Publish the new DID log containing the two new entries.
    18. +
    +
  • +
+

§ Post Quantum Attacks

+

One of the potential benefits of this approach to pre-rotation is that it is +“post-quantum safe”. The idea is that in a post-quantum world, the availability +of the published key and signatures may enable the calculation of the +corresponding private key. Since the pre-rotation value is a hash of the +nextKey and not the public key itself, a post-quantum attack would not +compromise that key, and so a further rotation by the attacker would not be +possible. If there was a (suspected) need to transition to using a quantum-safe +key, the same process listed above would be used, but key reference and the +pre-rotation hash added into the second DID log entry would presumably +both be for quantum-safe keys.

+

§ Challenges in Using Pre-Rotation

+

This draft specification states that once pre-rotation is enabled (via DID log entry parameter), it MUST apply to all of the keys in the +DIDDoc. However, we’re not sure if that is needed, or if the pre-rotation should +only apply to keys that are authorized to update the DID.

+

Key management is hard enough without having to maintain isolated key generation +environments for creating keys for different purposes. Enabling connectivity between +the key generation environments to enable automated key rotation while maintaining the +key recovery environment as “isolated” is technically challenging.

+

§ Using DID Portability

+

As noted in the DID Portability section of the +specification, a did:tdw DID can be renamed (ported) by changing the id DID string in +the DIDDoc to one that resolves to a different HTTPS URL, as long as the +specified conditions are met.

+

While the impact of the feature is in fact the creation of a new DID, we think +there is significant value in some use cases for supporting the specified +capability. Ideally, the HTTPS URL for the “old” DID is changed to a redirect to +the new DID, allowing for a seamless, verifiable evolution of the DID.

+

An interesting example use case is a DID that replaces an email address hosted +by a particular service. The extra capabilities of having the identifier being a +DID vs. an email address is compelling enough, allowing it to be used for a +range of services beyond email. The portability benefit comes when the owner of +the DID decides to move to a new service, taking their DID with them. The +verifiable history carried over to the renamed DID hosted by the new service +provides assurance to those who interacted with the old DID (through chats, +emails, postings, etc.) that they are still engaging with the same entity, +despite the DID renaming. Compare that with what happens today when you switch +from one email provider to another, and you have to reach out to all your +contacts to assure them that you changed providers.

+

While portability is powerful, it must be used with care and only in use +cases where the capability is specifically required. When used, both the +pre-rotation and witnesses features of did:tdw SHOULD also be enabled.

+

§ Mergers, Acquisitions and Name Changes

+

Organizations change over time and such changes often involve names changes. +Name changes in turn trigger domain name changes, as organizations match their +Web location with their names. Mergers, acquisitions, and simple name changes, +all can cause an organization’s “known” domain name to change, including the +relinquishment of control over their previous domain name. When such changes +occur, it is very unlikely that just because the organization’s DIDs use the old +domain name will prevent the changes. Thus the DIDs need to “adapt” to the new +domain – the domain name portion of the DID has to change. Ideally, the old +location and domain can be retained and a web redirect used to resolve the old +DID to the new, but even if that cannot be done, the ability to use the same +SCID and retain the full history can be preserved.

+

§ DID Hosting Service Providers

+

Consider being able to replace the current identifiers we are given (email +addresses, phone numbers) with did:tdw DIDs. Comparable hosting platforms +might publish our DIDs for us (ideally, with us in custody of our own private +keys…). Those DIDs, with the inherent public keys can be used for many +purposes – encrypted email (hello PGP!), messaging, secure file sharing, and +more.

+

From time to time in that imagined future, we may want to move our DIDs +from one hosting service to another, just as we move from one email or mobile +provider to another. With DIDs that can move and retain the history, we can make +such moves smoothly. Contacts will see the change, but also see that the history +of the DID remains.

+

§ Challenges in Moving a DID

+

While we see great value (and even a hard requirement) for being able to move a +DID’s web location, it does create challenges in aligning with the +[DID-CORE] specification. These challenges are listed below.

+

Moving a did:tdw is actually the (partial or complete) deactivation of the old +DID and the creation of a new DID. The use of the SCID and the way it +is generated is designed to prevent an attacker from being able to create a DID +they control but with the same SCID as existing DID. Thus, “finding” a did:tdw +with the same SCID implies the DIDs are the same. That can be verified by +processing the DID Log.

+

By retaining the incrementing of the versionId after a move, the “new” DID +does not start at versionId of 1. Further, resolving <new-did>?versionId=1 +is going to return a DIDDoc with the top-level id equal to the <old-did>. +This is useful from a business perspective, but unexpected from a +[DID-CORE] perspective.

+

§ Using High Assurance DIDs with DNS

+

The High Assurance DIDs with DNS mechanism that can be used with did:web +applies equally well with did:tdw. A DID Controller publishing a +did:tdw could use the mechanisms defined in the High Assurance DIDs with DNS +specification despite did:tdw DIDs not (yet) being explicitly called out in +the High Assurance DIDs with DNS specification. In particular, as did:tdw +uses the same DID-to-HTTP transformation, publishing the expected DNS Domain +records, and adding the required verification method and Data Integrity +proof to their DIDDoc is done as defined in the High Assurance DIDs +with DNS specification. Likewise, a resolver can include code to check to see if +the DID Controller published the High Assurance DIDs with DNS +specification DNS records and use those to further verify the DID.

+

Alternatively, since did:tdw is not mentioned in the High Assurance DIDs with +DNS specification, a did:tdw DID Controller could use the “not did:web” +technique described in that specification and include a dnsValidationDomain +entry in the DIDDoc to explicitly denote where to find the DNS records to use in +binding the DID to the DNS domain. This technique could also be used with +did:tdw (and did:web for that matter) if the DID is published on a platform +(such as GitHub) and the controller wants to bind it to its DNS domain.

+

§ Future Possibilities

+

In the future, as did:tdw becomes more accepted, we would like to see +did:tdw explicitly added to the High Assurance DIDs with DNS specification +beside did:web.

+

Since did:tdw and the High Assurance DIDs with DNS specification both have +the goal of adding methods for additional verifications of the DID, the support +for did:tdw in the High Assurance DIDs with DNS could be more specific to +the DID Method. For example, the key in the DNS record could be a required +did:tdw witness, with its Data Integrity proof being a part of the +DID log entry rather than in the DIDDoc itself.

+

§ Witnesses

+

The term “witness” is often used in the decentralized trust space to refer to +participants in an ecosystem that oversee the evolution of an identifier +according to some ecosystem-specific governance framework. The goal is for a +witness to collect, verify and approve data about the identifier and +share it with others that trust the witness so they don’t need to do +that work themselves. The extra participants are intended to identify both +malicious attackers of the identifier, and malicious use of the identifier by +the DID Controller.

+

Witnesses play an explicit function in did:tdw. When used by a DID, witnesses (themselves identified by DIDs) are sent +pending DID log entries prepared by the DID Controller. The +witnesses verify the log entry using their copy of the +“current state” of the DID, and then “approve” the update, according to the +governance they use to define what “approval” means. For example, a witness might interact with another party (perhaps even a person) to confirm +that the DID Controller created the log entry. Once the witness has both verified and approved the change, they express that approval +by creating a Data Integrity proof that is chained to the data proof created by the DID Controller, and send the proof +back to the DID Controller. Once the number of data integrity +proofs received by the DID Controller from the witnesses has +exceeded a threshold, the DID Controller adds those proofs to their own +data integrity proof in the log entry. Next, the DID adds the log entry to the DID log and publishes +the updated DIDDoc. A DID Controller relying on witnesses +cannot independently publish an update to their DID – they must get and publish +the witness approval proofs.

+

The application of witnesses is very much dependent on the governance +of the ecosystem. Such governance is outside the scope of the did:tdw +specification, and up to those deploying did:tdw DIDs. Hence, a DID that controls a series of DIDs and uses those DIDs as witnesses adds no additional trust or security to a DID if no properly defined +governance is in place. In particular, in order for witnesses to add +security and trust to a DID requires the members of an ecosystem to agree to the +defined governance. A witness could be an “endorser” of a set of DIDs +that are part of an ecosystem, with the act of witnessing the updates conveying +through their approval that the DIDs are a legitimate participant in the +ecosystem. Witnesses can also be used as a form of “two-factor +authentication” of a change, such as having a public key published as a DNS +record used as a witness for the DID. Such an addition means that an +attacker would need to compromise both the web-publishing infrastructure of the +DID Controller (where they publish the DID’s did.jsonl file) as well as its +DNS entry.

+

did:tdw witnesses have been specified to be simple to implement and use. Their +power and effectiveness will come in how they are deployed within specific, +governed ecosystems.

+

§ did:tdw Example

+

The following shows the evolution of a did:tdw from inception through several +versions, showing the DID, DIDDoc, DID Log, and some of the +intermediate data structures.

+

The examples are aligned with version 0.3 of the did:tdw specification.

+

In some of the following examples the data for the DID log entries is displayed +as prettified JSON for readability. In the log itself, the JSON has all +whitespace removed, and each line ends with a CR, per the JSON Lines convention.

+

§ DID Creation Data

+

These examples show the important structures used in the Create (Register) operation for a did:tdw DID.

+

§ Input to the SCID Generation Process with Placeholders

+

The following JSON is an example of the input that the DID Controller +constructs and passes into the +SCID Generation Process. In this example, the DIDDoc is +particularly boring, containing the absolute minimum for a valid DIDDoc.

+

This example includes both the initial “authorized keys” to sign the Data Integrity proof +(updateKeys) and the pre-rotation commitment to the next authorization keys (nextKeyHashes). Both +are in the parameters item in the log entry.

+
[
+  "{SCID}",
+  "2024-07-29T17:00:27Z",
+  {
+    "prerotation": true,
+    "updateKeys": [
+      "z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc"
+    ],
+    "nextKeyHashes": [
+      "QmcbM5bppyT4yyaL35TQQJ2XdSrSNAhH5t6f4ZcuyR4VSv"
+    ],
+    "method": "did:tdw:0.3",
+    "scid": "{SCID}"
+  },
+  {
+    "value": {
+      "@context": [
+        "https://www.w3.org/ns/did/v1",
+        "https://w3id.org/security/multikey/v1"
+      ],
+      "id": "did:tdw:{SCID}:domain.example"
+    }
+  }
+]
+
+

§ Output of the SCID Generation Process

+

After the SCID is generated, the literal {SCID} placeholders are +replaced by the generated SCID value (below). This JSON is the input to +the entryHash generation process – +with the SCID as the first item of the array. Once the process has run, +the version number of this first version of the DID (1), a dash - and the +resulting output hash replace the SCID as the first item in the array +– the versionId.

+
[
+  "Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu",
+  "2024-07-29T17:00:27Z",
+  {
+    "prerotation": true,
+    "updateKeys": [
+      "z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc"
+    ],
+    "nextKeyHashes": [
+      "QmcbM5bppyT4yyaL35TQQJ2XdSrSNAhH5t6f4ZcuyR4VSv"
+    ],
+    "method": "did:tdw:0.3",
+    "scid": "Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu"
+  },
+  {
+    "value": {
+      "@context": [
+        "https://www.w3.org/ns/did/v1",
+        "https://w3id.org/security/multikey/v1"
+      ],
+      "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example"
+    }
+  }
+]
+
+

§ Data Integrity Proof Generation and First Log Entry

+

The last step in the creation of the first log entry is the generation +of the data integrity proof. One of the keys in the updateKeys parameter MUST be used (in the form of a did:key) to generate the +signature in the proof, with the versionId value (item 1 of the did log) used as the challenge item. The generated proof is added to the JSON as the fifth item, and the entire array becomes the first entry in the +DID Log.

+

The following is the JSON prettified version of the entry log file that is published +as the did.jsonl file. When published, all extraneous whitespace is removed, as +shown in the block below the pretty-printed version.

+
[
+  "1-QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ",
+  "2024-07-29T17:00:27Z",
+  {
+    "prerotation": true,
+    "updateKeys": [
+      "z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc"
+    ],
+    "nextKeyHashes": [
+      "QmcbM5bppyT4yyaL35TQQJ2XdSrSNAhH5t6f4ZcuyR4VSv"
+    ],
+    "method": "did:tdw:0.3",
+    "scid": "Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu"
+  },
+  {
+    "value": {
+      "@context": [
+        "https://www.w3.org/ns/did/v1",
+        "https://w3id.org/security/multikey/v1"
+      ],
+      "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example"
+    }
+  },
+  [
+    {
+      "type": "DataIntegrityProof",
+      "cryptosuite": "eddsa-jcs-2022",
+      "verificationMethod": "did:key:z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc#z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc",
+      "created": "2024-07-29T17:00:27Z",
+      "proofPurpose": "authentication",
+      "challenge": "1-QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ",
+      "proofValue": "zDk24L4vbVrFm5CPQjRD9KoGFNcV6C3ub1ducPQEvDQ39U68GiofAndGbdG9azV6r78gHr1wKnKNPbMz87xtjZtcq9iwN5hjLptM9Lax4UeMWm9Xz7PP4crToj7sZnvyb3x4"
+    }
+  ]
+]
+
+

The same content “un-prettified”, as it is found in the did.jsonl file:

+
["1-QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ", "2024-07-29T17:00:27Z", {"prerotation": true, "updateKeys": ["z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc"], "nextKeyHashes": ["QmcbM5bppyT4yyaL35TQQJ2XdSrSNAhH5t6f4ZcuyR4VSv"], "method": "did:tdw:0.3", "scid": "Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu"}, {"value": {"@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/multikey/v1"], "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example"}}, [{"type": "DataIntegrityProof", "cryptosuite": "eddsa-jcs-2022", "verificationMethod": "did:key:z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc#z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc", "created": "2024-07-29T17:00:27Z", "proofPurpose": "authentication", "challenge": "1-QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ", "proofValue": "zDk24L4vbVrFm5CPQjRD9KoGFNcV6C3ub1ducPQEvDQ39U68GiofAndGbdG9azV6r78gHr1wKnKNPbMz87xtjZtcq9iwN5hjLptM9Lax4UeMWm9Xz7PP4crToj7sZnvyb3x4"}]]
+
+

§ did:web Version of DIDDoc

+

As noted in the publishing a parallel did:web +DID section of this specification a did:tdw can be published +by replacing did:tdw with did:web in the DIDDoc, adding an alsoKnownAs entry for the did:tdw +and publishing the resulting DIDDoc at did.json, logically beside the did.jsonl file.

+

Here is what the did:web DIDDoc looks like for the did:tdw above.

+
{
+  "@context": [
+    "https://www.w3.org/ns/did/v1",
+    "https://w3id.org/security/multikey/v1"
+  ],
+  "id": "did:web:domain.example",
+  "alsoKnownAs": ["did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example"]
+}
+
+

§ Version 2 of the DIDDoc

+

Time passes, and the DID Controller of the did:tdw DID decides to +update its DID to a new version, version 2. In this case, the only change +the DID Controller makes is transition the authorization key to +the pre-rotation key.

+

§ Version 2 Entry Hashing Input

+

To generate a new version of the DID, the DID Controller needs to +provide the existing DID log file, the updated parameters, and the new DIDDoc. +The following processing is done to create the new DID log entry:

+
    +
  • The versionId from the previous (first) log entry is made the first item in the new log entry.
  • +
  • The versionTime is generated as the current time, and made the new versionTime (second) item.
  • +
  • The parameters entry passed in is processed. In this case, since the +updateKeys array is updated, and pre-rotation is active, the a +verification is done to ensure that the hash of the updateKeys are found in +the nextKeyHashes item from version 1 of the DID. As required by the did:tdw +specification, a new nextKeyHashes is included in the parameters.
  • +
  • The new (but unchanged) DIDDoc is included in its entirety, as the value of value, set as the third item in the array. +
      +
    • The implementation could have used JSON Patch to generate value of the patch item.
    • +
    +
  • +
  • The resulting array is passed into the entryHash generation +process which outputs the +entryHash for this log entry. Once again, the first item +(versionId) in the log entry is replaced by the version number (the +previous version number plus 1), a dash (-), and the new entryHash.
  • +
  • The data integrity proof is generated added to the log entry +as the sixth item, and the entire entry is added to the existing DID.
  • +
+

The DID log file can now be published, optionally with an updated version of the corresponding did:web DID.

+

The following is the JSON pretty-print log entry for the second version of an example did:tdw. Things to note in this example:

+
    +
  • The data integrity proof verificationMethod is the did:key from the first log entry, and the challenge is the versionId from this log entry.
  • +
  • A new updateKeys item in the parameters has been added, a commit to a future key that will control updates to the DID.
  • +
+
[
+  "2-QmY2v1VzkeMxF7MSfrLfZswQ74Y6FfrMR1LmuvPJQJwhi6",
+  "2024-07-29T17:00:28Z",
+  {
+    "updateKeys": [
+      "z82Lkvgj5NKYhoFh4hWzax9WicQaVDphN8MMzR3JZhontVfHaoGd9JbC4QRpDvmjQH3BLeQ"
+    ],
+    "nextKeyHashes": [
+      "QmcCbGzGNr2EFduauzCoh3Hwt1GkRW4Gnkk5nxbr3625de"
+    ]
+  },
+  {
+    "value": {
+      "@context": [
+        "https://www.w3.org/ns/did/v1",
+        "https://w3id.org/security/multikey/v1"
+      ],
+      "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example"
+    }
+  },
+  [
+    {
+      "type": "DataIntegrityProof",
+      "cryptosuite": "eddsa-jcs-2022",
+      "verificationMethod": "did:key:z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc#z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc",
+      "created": "2024-07-29T17:00:28Z",
+      "proofPurpose": "authentication",
+      "challenge": "2-QmY2v1VzkeMxF7MSfrLfZswQ74Y6FfrMR1LmuvPJQJwhi6",
+      "proofValue": "z2VDUyVapPpb6rC4YbLZRLcWS2zg9o53JU97QjNQYH7JvGs5Ccnf2b647Gw96G5N8rvEKc77uQTGqYvLJ6zrqNwGnqNLraTPD2AL2rR2eUiRKnM5KhbwWumDy5eqmTumm1FWp"
+    }
+  ]
+]
+
+

§ Log File For Version 2

+

The new version 2 did.jsonl file contains two entries, one for each version +of the DIDDoc.

+
["1-QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ", "2024-07-29T17:00:27Z", {"prerotation": true, "updateKeys": ["z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc"], "nextKeyHashes": ["QmcbM5bppyT4yyaL35TQQJ2XdSrSNAhH5t6f4ZcuyR4VSv"], "method": "did:tdw:0.3", "scid": "Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu"}, {"value": {"@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/multikey/v1"], "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example"}}, [{"type": "DataIntegrityProof", "cryptosuite": "eddsa-jcs-2022", "verificationMethod": "did:key:z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc#z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc", "created": "2024-07-29T17:00:27Z", "proofPurpose": "authentication", "challenge": "1-QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ", "proofValue": "zDk24L4vbVrFm5CPQjRD9KoGFNcV6C3ub1ducPQEvDQ39U68GiofAndGbdG9azV6r78gHr1wKnKNPbMz87xtjZtcq9iwN5hjLptM9Lax4UeMWm9Xz7PP4crToj7sZnvyb3x4"}]]
+["2-QmY2v1VzkeMxF7MSfrLfZswQ74Y6FfrMR1LmuvPJQJwhi6", "2024-07-29T17:00:28Z", {"updateKeys": ["z82Lkvgj5NKYhoFh4hWzax9WicQaVDphN8MMzR3JZhontVfHaoGd9JbC4QRpDvmjQH3BLeQ"], "nextKeyHashes": ["QmcCbGzGNr2EFduauzCoh3Hwt1GkRW4Gnkk5nxbr3625de"]}, {"value": {"@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/multikey/v1"], "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example"}}, [{"type": "DataIntegrityProof", "cryptosuite": "eddsa-jcs-2022", "verificationMethod": "did:key:z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc#z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc", "created": "2024-07-29T17:00:28Z", "proofPurpose": "authentication", "challenge": "2-QmY2v1VzkeMxF7MSfrLfZswQ74Y6FfrMR1LmuvPJQJwhi6", "proofValue": "z2VDUyVapPpb6rC4YbLZRLcWS2zg9o53JU97QjNQYH7JvGs5Ccnf2b647Gw96G5N8rvEKc77uQTGqYvLJ6zrqNwGnqNLraTPD2AL2rR2eUiRKnM5KhbwWumDy5eqmTumm1FWp"}]]
+
+

§ Log File For Version 3

+

The same process is repeated for version 3 of the DID. In this case:

+
    +
  • The DIDDoc is changed, and a patch generated. +
      +
    • an authentication method is added.
    • +
    • two services are added.
    • +
    +
  • +
  • No changes are made to the authorized keys to update the DID. As a result, the parameters entry is empty ({}), and the parameters in effect from previous versions of the DID remain in effect.
  • +
+

Here is the pretty-printed log entry:

+
[
+  "3-QmNwk72WkEjUMQxqkxYoKWNx8Y1pDiGUZCn9PpeLtfPtyk",
+  "2024-07-29T17:00:28Z",
+  {},
+  {
+    "patch": [
+      {
+        "op": "add",
+        "path": "/authentication",
+        "value": [
+          "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#z6Mkq57k27wL26zrxpvGVdEsCKe5kfpJhzy7GciVUfmosTdv"
+        ]
+      },
+      {
+        "op": "add",
+        "path": "/assertionMethod",
+        "value": [
+          "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#z6Mkq57k27wL26zrxpvGVdEsCKe5kfpJhzy7GciVUfmosTdv"
+        ]
+      },
+      {
+        "op": "add",
+        "path": "/service",
+        "value": [
+          {
+            "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#domain",
+            "type": "LinkedDomains",
+            "serviceEndpoint": "https://domain.example"
+          },
+          {
+            "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#whois",
+            "type": "LinkedVerifiablePresentation",
+            "serviceEndpoint": "https://domain.example/.well-known/whois.vc"
+          }
+        ]
+      },
+      {
+        "op": "add",
+        "path": "/@context/2",
+        "value": "https://identity.foundation/.well-known/did-configuration/v1"
+      },
+      {
+        "op": "add",
+        "path": "/@context/3",
+        "value": "https://identity.foundation/linked-vp/contexts/v1"
+      }
+    ]
+  },
+  [
+    {
+      "type": "DataIntegrityProof",
+      "cryptosuite": "eddsa-jcs-2022",
+      "verificationMethod": "did:key:z82Lkvgj5NKYhoFh4hWzax9WicQaVDphN8MMzR3JZhontVfHaoGd9JbC4QRpDvmjQH3BLeQ#z82Lkvgj5NKYhoFh4hWzax9WicQaVDphN8MMzR3JZhontVfHaoGd9JbC4QRpDvmjQH3BLeQ",
+      "created": "2024-07-29T17:00:28Z",
+      "proofPurpose": "authentication",
+      "challenge": "3-QmNwk72WkEjUMQxqkxYoKWNx8Y1pDiGUZCn9PpeLtfPtyk",
+      "proofValue": "z2TBssHyJj7dB4LDGjHWm3EfHhBiu534w4ucRF95XG3KzLg4m5kjtYbupGmf4txjqQRPko8Qd8PGeHgykWdutHXxJUmvvpGuiJxNBRpfwfKxnsbrT7jWeT6GqaFYqqkDcCG35"
+    }
+  ]
+]
+
+

Here is the log entry for just version 3 of the DID.

+
["3-QmNwk72WkEjUMQxqkxYoKWNx8Y1pDiGUZCn9PpeLtfPtyk", "2024-07-29T17:00:28Z", {}, {"patch": [{"op": "add", "path": "/authentication", "value": ["did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#z6Mkq57k27wL26zrxpvGVdEsCKe5kfpJhzy7GciVUfmosTdv"]}, {"op": "add", "path": "/assertionMethod", "value": ["did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#z6Mkq57k27wL26zrxpvGVdEsCKe5kfpJhzy7GciVUfmosTdv"]}, {"op": "add", "path": "/service", "value": [{"id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#domain", "type": "LinkedDomains", "serviceEndpoint": "https://domain.example"}, {"id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#whois", "type": "LinkedVerifiablePresentation", "serviceEndpoint": "https://domain.example/.well-known/whois.vc"}]}, {"op": "add", "path": "/@context/2", "value": "https://identity.foundation/.well-known/did-configuration/v1"}, {"op": "add", "path": "/@context/3", "value": "https://identity.foundation/linked-vp/contexts/v1"}]}, [{"type": "DataIntegrityProof", "cryptosuite": "eddsa-jcs-2022", "verificationMethod": "did:key:z82Lkvgj5NKYhoFh4hWzax9WicQaVDphN8MMzR3JZhontVfHaoGd9JbC4QRpDvmjQH3BLeQ#z82Lkvgj5NKYhoFh4hWzax9WicQaVDphN8MMzR3JZhontVfHaoGd9JbC4QRpDvmjQH3BLeQ", "created": "2024-07-29T17:00:28Z", "proofPurpose": "authentication", "challenge": "3-QmNwk72WkEjUMQxqkxYoKWNx8Y1pDiGUZCn9PpeLtfPtyk", "proofValue": "z2TBssHyJj7dB4LDGjHWm3EfHhBiu534w4ucRF95XG3KzLg4m5kjtYbupGmf4txjqQRPko8Qd8PGeHgykWdutHXxJUmvvpGuiJxNBRpfwfKxnsbrT7jWeT6GqaFYqqkDcCG35"}]]
+
+

And so on…

+

§ References

+

+

+
DID-CORE
+
+ Decentralized Identifiers (DIDs) v1.0. + Manu Sporny; Amy Guy; Markus Sabadello; Drummond Reed; 2022-07-19. Status: REC. +
+ +
RFC1035
+
+ Domain names - implementation and specification. + P. Mockapetris; 1987-11. Status: Internet Standard. +
+ +
RFC1123
+
+ Requirements for Internet Hosts - Application and Support. + R. Braden, Ed.; 1989-10. Status: Internet Standard. +
+ +
RFC2181
+
+ Clarifications to the DNS Specification. + R. Elz; R. Bush; 1997-07. Status: Proposed Standard. +
+ +
RFC2234
+
+ Augmented BNF for Syntax Specifications: ABNF. + D. Crocker, Ed.; P. Overell; 1997-11. Status: Proposed Standard. +
+ +
RFC3912
+
+ WHOIS Protocol Specification. + L. Daigle; 2004-09. Status: Draft Standard. +
+ +
RFC3986
+
+ Uniform Resource Identifier (URI): Generic Syntax. + T. Berners-Lee; R. Fielding; L. Masinter; 2005-01. Status: Internet Standard. +
+ +
RFC4033
+
+ DNS Security Introduction and Requirements. + R. Arends; R. Austein; M. Larson; D. Massey; S. Rose; 2005-03. Status: Proposed Standard. +
+ +
RFC4034
+
+ Resource Records for the DNS Security Extensions. + R. Arends; R. Austein; M. Larson; D. Massey; S. Rose; 2005-03. Status: Proposed Standard. +
+ +
RFC4035
+
+ Protocol Modifications for the DNS Security Extensions. + R. Arends; R. Austein; M. Larson; D. Massey; S. Rose; 2005-03. Status: Proposed Standard. +
+ +
RFC5895
+
+ Mapping Characters for Internationalized Domain Names in Applications (IDNA) 2008. + P. Resnick; P. Hoffman; 2010-09. Status: Informational. +
+ +
RFC6234
+
+ US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF). + D. Eastlake 3rd; T. Hansen; 2011-05. Status: Informational. +
+ +
RFC6902
+
+ JavaScript Object Notation (JSON) Patch. + P. Bryan, Ed.; M. Nottingham, Ed.; 2013-04. Status: Proposed Standard. +
+ +
RFC8484
+
+ DNS Queries over HTTPS (DoH). + P. Hoffman; P. McManus; 2018-10. Status: Proposed Standard. +
+ +
RFC8785
+
+ JSON Canonicalization Scheme (JCS). + A. Rundgren; B. Jordan; S. Erdtman; 2020-06. Status: Informational. +
+ +
+

+

§ did:tdw Version Changelog

+

The following lists the substantive changes in each version of the specification.

+
    +
  • Version 0.3 +
      +
    • Removes the cryptosuite parameter, moving it to implied based on the method parameter.
    • +
    • Change base32 encoding with base58btc, as it offers a better expansion rate.
    • +
    • Remove the step to extract part of the base58btc result during the generation of the SCID.
    • +
    • Use multihash in the SCID to differentiate the different hash function outputs.
    • +
    +
  • +
  • Version 0.2 +
      +
    • Changes the location of the SCID in the DID to always be the first +component after the DID Method prefix – did:tdw:<scid>:....
    • +
    • Adds the parameter portable to enable the capability to move a +did:tdw during the creation of the DID.
    • +
    • Removes the first two Log Entry items entryHash and versionId +and replacing them with the new versionId as the first item in each log. The new versionId takes the form <version number>-<entryHash>, +where <version number> is the incrementing integer of version of the +entry: 1, 2, 3, etc.
    • +
    • The <did>/whois media type is changed to application/vp and the file is +changed to whois.vp to match the IANA registration of a Verifiable.
    • +
    +
  • +
+ +
+ +
+ + + +
+ + + + + +
+
    +
    + + +
    + Table of Contents + +
    +
    + + +
    +
    + +
    +
    + undefined +
    + + + + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..d3ced4c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4756 @@ +{ + "name": "trustdidweb", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "trustdidweb", + "version": "1.0.0", + "license": "Apache 2.0", + "dependencies": { + "spec-up": "github:brianorwhatever/spec-up#master" + } + }, + "node_modules/@traptitech/markdown-it-katex": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@traptitech/markdown-it-katex/-/markdown-it-katex-3.3.0.tgz", + "integrity": "sha512-9PM7tVjLn+mRYCTd8Aps8yuKOH8aRttZ8sMyVYkKltlLMDxFX1LfclZuRv01kct/Q7Euwe4neY/nB1wZNLjblg==", + "dependencies": { + "katex": "^0.12.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dependencies": { + "ansi-wrap": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha512-HrgGIZUl8h2EHuZaU9hTR/cU5nhKxpVE1V6kdGsQ8e4zirElJ5fvtfc8N7Q1oq1aatO275i8pUFUCpNWCAnVWw==", + "dependencies": { + "ansi-wrap": "0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha512-WLbYiXzD3y/ATLZFufV/rZvWdZOs+Z/+5v1rBZ463Jn398pa6kcde27cvozYnBoxXblGZTFfoPpsaEw0orU5BA==", + "dependencies": { + "buffer-equal": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha512-A2BETWCqhsecSvCkWAeVBFLH6sXEUGASuzkpjL3GR1SlL/PWL6M3J8EAAld2Uubmh39tvkJTqC9LeLHCUKmFXA==", + "dependencies": { + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha512-tVqVTHt+Q5Xb09qRkbu+DidW1yYzz5izWS2Xm2yFm7qJnmUfz4HPzNxbHkdRJbz2lrqI7S+z17xNYdFcBBO8Hw==", + "dependencies": { + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha512-BC4Yl89vneCYfpLrs5JU2aAu9/a+xWbeKhvISg9PT7eWFB9UlRvI+rKEtk6mgxWr3dSkk9gQ8hCrdqt06NXPdw==", + "dependencies": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-initial/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dependencies": { + "is-number": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-last/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dependencies": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/async-each": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.6.tgz", + "integrity": "sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/axios": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.2.tgz", + "integrity": "sha512-87otirqUw3e8CzHTMO+/9kh/FSgXt/eVDvipijwDtEuwbkySWZ9SBm6VEubmJ/kLKEoLQV/POhxXFb66bfekfg==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", + "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==" + }, + "node_modules/cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dependencies": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha512-5D2XXSpkOnleOI21TG7p3T0bGAsZ/XknZpKBmGYyluO8pw4zA3K8ZlrBIbC4FXg3m6z/RNFiUFfT2sQK01+UHA==", + "dependencies": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-props": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", + "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", + "dependencies": { + "each-props": "^1.3.2", + "is-plain-object": "^5.0.0" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cssstyle": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", + "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", + "dependencies": { + "rrweb-cssom": "^0.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cssstyle/node_modules/rrweb-cssom": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", + "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==" + }, + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dependencies": { + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha512-2xaP6GiwVwOEbXCGoJ4ufgC76m8cj805jrghScewJC2ZDsb9U0b4BIrba+xt/Uytyd0HvQ6+WymSRTfnYj59GQ==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dependencies": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, + "node_modules/each-props/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/emojione": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/emojione/-/emojione-3.1.7.tgz", + "integrity": "sha512-ITb0rrx6iuJKBnThRUE0uiGkwriwnY+919vxsAF+EqBHXhyjCTAcUo/nPNWodHaOJvKGdI1mel2o6TyyxBjjLw==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dependencies": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==" + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/find-pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-pkg-dir/-/find-pkg-dir-2.0.0.tgz", + "integrity": "sha512-FQSkqcdGa2Rsg2ismCcS5v/mf6ieB0RcOBQhIEWurusYkIZRpKnumugzdbCqKZXsbCUdkni7aoIgpUXRL+HrxQ==", + "dependencies": { + "inspect-with-kind": "^1.0.5" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fined/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/font-awesome-icon-chars": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/font-awesome-icon-chars/-/font-awesome-icon-chars-1.3.0.tgz", + "integrity": "sha512-8Jyv4DApOm6OK6hMVgDeymDEBmztLoXU9iUiIadKsS/FfgeRqFQW8PUwG5pLVoz8yNPaRn7JgWralUV6Fms9nA==" + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fs-mkdirp-stream/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dependencies": { + "sparkles": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-clean-css": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-4.3.0.tgz", + "integrity": "sha512-mGyeT3qqFXTy61j0zOIciS4MkYziF2U594t2Vs9rUnpkEHqfu6aDITMp8xOvZcvdX61Uz3y1mVERRYmjzQF5fg==", + "dependencies": { + "clean-css": "4.2.3", + "plugin-error": "1.0.1", + "through2": "3.0.1", + "vinyl-sourcemaps-apply": "0.2.1" + } + }, + "node_modules/gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "dependencies": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-cli/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/gulp-cli/node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "node_modules/gulp-cli/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + }, + "node_modules/gulp-cli/node_modules/yargs": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", + "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", + "dependencies": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.1" + } + }, + "node_modules/gulp-cli/node_modules/yargs-parser": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", + "dependencies": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + }, + "node_modules/gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha512-a2scActrQrDBpBbR3WUZGyGS1JEPLg5PZJdIa7/Bi3GuKAmPYDK6SFhy/NZq5R8KsKKFvtfR0fakbUCcKGCCjg==", + "dependencies": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-concat/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/gulp-terser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gulp-terser/-/gulp-terser-1.2.0.tgz", + "integrity": "sha512-lf+jE2DALg2w32p0HRiYMlFYRYelKZPNunHp2pZccCYrrdCLOs0ItbZcN63yr2pbz116IyhUG9mD/QbtRO1FKA==", + "dependencies": { + "plugin-error": "^1.0.1", + "terser": "^4.0.0", + "through2": "^3.0.1", + "vinyl-sourcemaps-apply": "^0.2.1" + } + }, + "node_modules/gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha512-hm6N8nrm3Y08jXie48jsC55eCZz9mnb4OirAStEk2deqeyhXU3C1otDVh+ccttMuc1sBi6RX6ZJ720hs9RCvgw==", + "dependencies": { + "glogg": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/inspect-with-kind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/inspect-with-kind/-/inspect-with-kind-1.0.5.tgz", + "integrity": "sha512-MAQUJuIo7Xqk8EVNP+6d3CKq9c80hi4tjIbIAT6lmGW9W6WzlHiu9PS8uSuUYU+Do+j1baiFp3H25XEVxDIG2g==", + "dependencies": { + "kind-of": "^6.0.2" + } + }, + "node_modules/inspect-with-kind/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", + "integrity": "sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==", + "dependencies": { + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-descriptor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz", + "integrity": "sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==", + "dependencies": { + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-descriptor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" + }, + "node_modules/is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jsdom": { + "version": "24.1.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.3.tgz", + "integrity": "sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==", + "dependencies": { + "cssstyle": "^4.0.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.4", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/just-debounce": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", + "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==" + }, + "node_modules/katex": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.12.0.tgz", + "integrity": "sha512-y+8btoc/CK70XqcHqjxiGWBOeIL8upbS0peTPXTvgrh21n1RiWWcIpSWM+4uXq+IAgNh9YYQWdc7LVDPDAEEAg==", + "dependencies": { + "commander": "^2.19.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dependencies": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/liftoff/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/make-iterator/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.2.5.tgz", + "integrity": "sha512-xLIjLQmtym3QpoY9llBgApknl7pxAcN3WDRc2d3rwpl+/YvDZHPmKscGs+L6E05xf2KrCXPBvosWt7MZukwSpQ==", + "peerDependencies": { + "markdown-it": "*" + } + }, + "node_modules/markdown-it-attrs": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/markdown-it-attrs/-/markdown-it-attrs-4.1.4.tgz", + "integrity": "sha512-53Zfv8PTb6rlVFDlD106xcZHKBSsRZKJ2IW/rTxEJBEVbVaoxaNsmRkG0HXfbHl2SK8kaxZ2QKqdthWy/QBwmA==", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "markdown-it": ">= 9.0.0" + } + }, + "node_modules/markdown-it-chart": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/markdown-it-chart/-/markdown-it-chart-0.2.0.tgz", + "integrity": "sha512-BFiWDlQACJlnXDolLxYTg7qHMh+LvJHgSAfNYZbyF3Fy+4aJaJALErvQfDxD/o5SfAOfTyMcxFTYgy8NbehwQQ==" + }, + "node_modules/markdown-it-container": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-2.0.0.tgz", + "integrity": "sha512-IxPOaq2LzrGuFGyYq80zaorXReh2ZHGFOB1/Hen429EJL1XkPI3FJTpx9TsJeua+j2qTru4h3W1TiCRdeivMmA==" + }, + "node_modules/markdown-it-deflist": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/markdown-it-deflist/-/markdown-it-deflist-2.1.0.tgz", + "integrity": "sha512-3OuqoRUlSxJiuQYu0cWTLHNhhq2xtoSFqsZK8plANg91+RJQU1ziQ6lA2LzmFAEes18uPBsHZpcX6We5l76Nzg==" + }, + "node_modules/markdown-it-icons": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/markdown-it-icons/-/markdown-it-icons-0.4.1.tgz", + "integrity": "sha512-FFo5pkIq5Ovdq53lJ+lzhVz9wl+JjNv5wDaQM2DPGWmmi4ygfYQjD1zgHdiTUWGxTLEioDlIyPwh8LMeQ74+zg==", + "dependencies": { + "emojione": "^3.1.2", + "font-awesome-icon-chars": "^1.3.0", + "markdown-it-regex": "^0.1.4" + } + }, + "node_modules/markdown-it-ins": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-ins/-/markdown-it-ins-2.0.0.tgz", + "integrity": "sha512-DhLLxseIg2C7+AULvoyVI+zMeufR0QFvXJ2o0oV013hN5HvBvNh2rbVtTdxZjI959+hgo2AA0aRdtEIUaKPbhg==" + }, + "node_modules/markdown-it-mark": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-mark/-/markdown-it-mark-2.0.0.tgz", + "integrity": "sha512-iT8ua0Bda8QrVwHDOUNw1eyCuL7irXeYch5n8zGS4tb7wsDIn7EjQZLjihKaijzBiL0ikfWL2zAvL/ECqTvsNA==" + }, + "node_modules/markdown-it-modify-token": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/markdown-it-modify-token/-/markdown-it-modify-token-1.0.2.tgz", + "integrity": "sha512-A1z8SrRYM0NfFwAhTN1NAiodKmP66HsvdZE/pchfWzcIW/UW8c4r7gXcQKxHr+dSzBndRz5Jsa/ApxAQUrzwbA==" + }, + "node_modules/markdown-it-multimd-table": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/markdown-it-multimd-table/-/markdown-it-multimd-table-4.2.3.tgz", + "integrity": "sha512-KepCr2OMJqm7IT6sOIbuqHGe+NERhgy66XMrc5lo6dHW7oaPzMDtYwR1EGwK16/blb6mCSg4jqityOe0o/H7HA==" + }, + "node_modules/markdown-it-prism": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-prism/-/markdown-it-prism-2.3.0.tgz", + "integrity": "sha512-ePtHY80gZyeje4bn3R3SL0jpd1C9HFaYffJW2Ma0YD+tspqa2v9TuVwUyFwboFu4jnFNcO8oPQROgbcYJbmBvw==", + "dependencies": { + "prismjs": "1.29.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/markdown-it-references": { + "version": "1.0.0-alpha.10", + "resolved": "https://registry.npmjs.org/markdown-it-references/-/markdown-it-references-1.0.0-alpha.10.tgz", + "integrity": "sha512-SBRt2wDluPDMrkAXPHfAdzNpYMHxijtLwEH4fhNhLsKApU0cwCGe4wzv/f3RnQBqr2xwyx1WDkxaFC4Yb/i8gw==", + "peerDependencies": { + "markdown-it": "*" + } + }, + "node_modules/markdown-it-regex": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/markdown-it-regex/-/markdown-it-regex-0.1.4.tgz", + "integrity": "sha512-EjsH5pYfKJRZ7t3fD1nD/KIk06hWT9ZoycOOc8n04BPgml6HleP/F9gSLWeQaUsPvSk5Yz2fr4iCY0bLp051bA==" + }, + "node_modules/markdown-it-sub": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-sub/-/markdown-it-sub-1.0.0.tgz", + "integrity": "sha512-z2Rm/LzEE1wzwTSDrI+FlPEveAAbgdAdPhdWarq/ZGJrGW/uCQbKAnhoCsE4hAbc3SEym26+W2z/VQB0cQiA9Q==" + }, + "node_modules/markdown-it-sup": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-sup/-/markdown-it-sup-1.0.0.tgz", + "integrity": "sha512-E32m0nV9iyhRR7CrhnzL5msqic7rL1juWre6TQNxsnApg7Uf+F97JOKxUijg5YwXz86lZ0mqfOnutoryyNdntQ==" + }, + "node_modules/markdown-it-task-lists": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz", + "integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==" + }, + "node_modules/markdown-it-textual-uml": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/markdown-it-textual-uml/-/markdown-it-textual-uml-0.1.3.tgz", + "integrity": "sha512-AMOt7HSOMnzJZ6KQq3wRimvTBc70ZxyVO97zHX66YXibykG/w2+iqNuDbjn/GlAyBU1WATdKkLAJNQ3ZsGWOkQ==" + }, + "node_modules/markdown-it-toc-and-anchor": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/markdown-it-toc-and-anchor/-/markdown-it-toc-and-anchor-4.2.0.tgz", + "integrity": "sha512-DusSbKtg8CwZ92ztN7bOojDpP4h0+w7BVOPuA3PHDIaabMsERYpwsazLYSP/UlKedoQjOz21mwlai36TQ04EpA==", + "dependencies": { + "clone": "^2.1.0", + "uslug": "^1.0.4" + } + }, + "node_modules/matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha512-LFgVbaHIHMqCRuCZyfCtUOq9/Lnzhi7Z0KFUE2fhD54+JN2jLh3hC02RLkqauJ3U4soU6H1J3tfj/Byk7GoEjA==", + "dependencies": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/matchdep/node_modules/findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g==", + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/matchdep/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/nan": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", + "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==", + "optional": true + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nwsapi": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", + "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==" + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", + "dependencies": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha512-naLhxxpUESbNkRqc35oQ2scZSJueHGQNUfMW/0U37IgN6tE2dgDWg3whf+NEliy3F/QysrO48XKUz/nGPe+AQw==", + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", + "dependencies": { + "readable-stream": "^2.0.1" + } + }, + "node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "dependencies": { + "path-root-regex": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dependencies": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/plugin-error/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/plugin-error/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/plugin-error/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dependencies": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha512-wigO8/O08XHb8YPzpDDT+QmRANfW6vLqxfaXm1YXhnFf3AkSLyjfG3GEFg4McZkmgL7KvCj5u2KczkvSP6NfHA==", + "dependencies": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remove-bom-stream/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==" + }, + "node_modules/repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha512-CHPV/GAglbIB1tnQgaiysb8H2yCy8WQ7lcEwQ/eT+kLj0QHV8LnJW0zpqpE7RSkrMSRoa+EBoag86clf7WAgSg==", + "dependencies": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==" + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated" + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "engines": { + "node": ">=0.12" + } + }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha512-Ny/iyOzSSa8M5ML46IAx3iXc6tfOsYU2R4AXi2UpHk60Zrgyq6eqPj/xiOfS0rRl/iiQ/rdJkVjw/5cdUyCntQ==", + "dependencies": { + "sver-compat": "^1.5.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated" + }, + "node_modules/sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==" + }, + "node_modules/spec-up": { + "version": "0.10.7", + "resolved": "git+ssh://git@github.com/brianorwhatever/spec-up.git#1e46f99a88be7f1a33a2e57876837f64f9837ace", + "dependencies": { + "@traptitech/markdown-it-katex": "3.3.0", + "axios": "0.21.2", + "find-pkg-dir": "2.0.0", + "fs-extra": "8.1.0", + "gulp": "4.0.2", + "gulp-clean-css": "4.3.0", + "gulp-concat": "2.6.1", + "gulp-terser": "1.2.0", + "jsdom": "^24.0.0", + "markdown-it": "13.0.1", + "markdown-it-anchor": "5.2.5", + "markdown-it-attrs": "4.1.4", + "markdown-it-chart": "^0.2.0", + "markdown-it-container": "^2.0.0", + "markdown-it-deflist": "^2.1.0", + "markdown-it-icons": "^0.4.1", + "markdown-it-ins": "^2.0.0", + "markdown-it-mark": "^2.0.0", + "markdown-it-modify-token": "1.0.2", + "markdown-it-multimd-table": "^4.1.3", + "markdown-it-prism": "^2.2.0", + "markdown-it-references": "1.0.0-alpha.10", + "markdown-it-sub": "^1.0.0", + "markdown-it-sup": "^1.0.0", + "markdown-it-task-lists": "2.1.1", + "markdown-it-textual-uml": "0.1.3", + "markdown-it-toc-and-anchor": "4.2.0", + "merge-stream": "2.0.0", + "pkg-dir": "4.2.0", + "prismjs": ">=1.24.0", + "yargs": "16.2.0" + } + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "engines": { + "node": "*" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==" + }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha512-aFTHfmjwizMNlNE6dsGmoAM4lHjL0CyiobWaFiXWSlD7cIxshW422Nb8KbXCmR6z+0ZEPY+daXJrDyh/vuwTyg==", + "dependencies": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, + "node_modules/terser": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/through2": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", + "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", + "dependencies": { + "readable-stream": "2 || 3" + } + }, + "node_modules/through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dependencies": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "node_modules/through2-filter/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==", + "dependencies": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/to-through/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==" + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dependencies": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unorm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", + "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "deprecated": "Please see https://github.com/lydell/urix#deprecated" + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uslug": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/uslug/-/uslug-1.0.4.tgz", + "integrity": "sha512-Jrbpp/NS3TvIGNjfJT1sn3/BCeykoxR8GbNYW5lF6fUscLkbXFwj1b7m4DvIkHm8k3Qr6Co68lbTmoZTMGk/ow==", + "dependencies": { + "unorm": ">= 1.0.0" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-fs/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha512-+oDh3KYZBoZC8hfocrbrxbLUeaYtQK7J5WU5Br9VqWqmCll3tFJqKp97GC9GmMsVIL0qnx2DgEDVxdo5EZ5sSw==", + "dependencies": { + "source-map": "^0.5.1" + } + }, + "node_modules/vinyl-sourcemaps-apply/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..bacfabd --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "trustdidweb", + "version": "1.0.0", + "description": "Trust DID Web (tdw).", + "main": "index.js", + "scripts": { + "edit": "node -e \"require('spec-up')()\"", + "render": "node -e \"require('spec-up')({ nowatch: true })\"", + "dev": "node -e \"require('spec-up')({ dev: true })\"" + }, + "keywords": [ + "decentralized identifier", + "DID", + "spec", + "trustdidweb", + "tdw" + ], + "author": "Stephen Curran", + "license": "Apache 2.0", + "bugs": { + "url": "https://github.com/decentralized-identity/trustdidweb/issues" + }, + "homepage": "https://github.com/decentralized-identity/trustdidweb#readme", + "dependencies": { + "spec-up": "github:brianorwhatever/spec-up#master" + } +} diff --git a/spec/abstract.md b/spec/abstract.md new file mode 100644 index 0000000..bbfbc27 --- /dev/null +++ b/spec/abstract.md @@ -0,0 +1,44 @@ +## Abstract + +Trust DID Web (`did:tdw`) is an enhancement to the `did:web` DID method, +providing complementary web-based features that address `did:web`'s +limitations. `did:tdw` features include: + +- Ongoing publishing of all DID Document ([[ref: DIDDoc]]) versions for a DID instead of, + or alongside a current `did:web` DID/DIDDoc. +- The same DID-to-HTTPS transformation as `did:web`. +- Supports the same [High Assurance DIDs with DNS] mechanism. +- The ability to resolve the full history of the DID using a verifiable chain of + updates to the [[ref: DIDDoc]] from genesis to deactivation. +- A [[ref: self-certifying identifier]] (SCID) for the DID. The [[ref: SCID]], globally unique and + embedded in the DID, is derived from the initial [[ref: DID log entry]]. It ensures the integrity + of the DID's history mitigating the risk of attackers creating a new object with + the same identifier. +- An optional mechanism for enabling [[ref: DID portability]] via the [[ref: SCID]], allowing + the DID's web location to be moved and the DID string to be updated, both while retaining + a connection to the predecessor DID(s) and preserving the DID's verifiable history. +- [[ref: DIDDoc]] updates contain a proof signed by the [[ref: DID Controllers]] *authorized* to + update the DID. +- An optional mechanism for publishing "pre-rotation" keys to prevent the loss of + control of a DID in cases where an active private key is compromised. +- An optional mechanism for having collaborating [[ref: witnesses]] + that approve of updates to the DID by a [[ref: DID Controller]] before publication. +- DID URL path handling that defaults (but can be overridden) to automatically + resolving `/path/to/file` by using a comparable DID-to-HTTPS translation + as for the [[ref: DIDDoc]]. +- A DID URL path `/whois` that defaults to automatically returning (if + published by the [[ref: DID controller]]) a [[ref: Verifiable Presentation]] containing + [[ref: Verifiable Credentials]] with the DID as the `credentialSubject`, + signed by the DID. + +[High Assurance DIDs with DNS]: https://datatracker.ietf.org/doc/draft-carter-high-assurance-dids-with-dns/ + +Combined, the additional features enable greater trust and security without +compromising the simplicity of `did:web`. + +The incorporation of the DID Core compatible "/whois" path, drawing inspiration +from the traditional WHOIS protocol [[spec:rfc3912]], offers an easy-to-use, +decentralized, trust registry. The `did:tdw` method aims to establish a more +trusted and secure web environment by providing robust verification processes +and enabling transparency and authenticity in the management of decentralized +digital identities. diff --git a/spec/definitions.md b/spec/definitions.md new file mode 100644 index 0000000..0fe219f --- /dev/null +++ b/spec/definitions.md @@ -0,0 +1,178 @@ +## Definitions + +[[def: base58btc]] + +~ Applies [[spec:draft-msporny-base58-03]] to convert +data to a `base58` encoding. Used in `did:tdw` for encoding hashes for [[ref: SCIDs]] and [[ref: entry hashes]]. + +[[def: Data Integrity]] + +~ [W3C Data +Integrity](https://www.w3.org/community/reports/credentials/CG-FINAL-data-integrity-20220722/) +is a specification of mechanisms for ensuring the authenticity and integrity of +structured digital documents using cryptography, such as digital signatures and +other digital mathematical proofs. + +[[def: Decentralized Identifier, Decentralized Identifiers]] + +~ Decentralized Identifiers (DIDs) [[spec:did-core]] are a type of identifier that enable +verifiable, decentralized digital identities. A DID refers to any subject (e.g., +a person, organization, thing, data model, abstract entity, etc.) as determined +by the controller of the DID. + +[[def: DIDDoc]] + +~ A DID Document as defined by the [[spec: DID-Core]] -- the document returned when a DID is resolved. + +[[def: DID:key]] + +~ `DID:key`... + +[[def: DID Log, DID Logs]] + +~ A DID Log is a list of [[ref: Entries]] one being added for each update of an entry item, +including new versions of the [[ref: DIDDoc]] or changed information necessary to generate or validate the DID. + +[[def: DID Log Entry, DID Log Entries, Entries, Log Entries]] + +~ A DID Log Entry is a JSON array of five items which define the authorized +transformation of a [[ref: DIDDoc]] from one version to the next. The initial entry +establishes the DID and version 1 of the [[ref: DIDDoc]]. All entries are stored +in the [[ref: DID Log]]. + +[[def: DID Method, DID Methods]] + +~ DID methods are the mechanism by which a particular type of DID and its +associated DID document are created, resolved, updated, and deactivated. DID +methods are defined using separate DID method specifications. This document is +the DID Method Specification for `DID:tdw`. + +[[def: DID Portability, DID:tdw portability, `DID:tdw` portability]] + +~ `did:tdw` [[ref: portability]] encompasses the ability to change the DID string for the +DID while retaining the [[ref: SCID]] and the history of the DID. This is useful +when forced to change (such as when an organization is acquired by another, +resulting in a change of domain names) and when changing DID hosting service +providers. + +[[def: did:web]] + +~ `did:web` as described in the [W3C specification](https://w3c-ccg.github.io/did-method-web/) +is a DID method that leverages the Domain Name System (DNS) to perform the DID operations. +It is valued for its simplicity and ease of deployment compared to [[ref: DID methods]] that are +based on distributed ledgers or blockchain technology, but also comes with increased +challenges related to trust and security. `did:web` provides a starting point for `did:tdw`, +which complements `did:web` with specific features to address the challenges +while still providing ease of deployment. + +[[def: eddsa-jcs-2022]] + +~ A cryptosuite defined for producing a [[ref: Data Integrity]] proof for an +unsecured input data document and verifying the [[ref: Data Integrity]] proof of +the secured document. More information on further operations and applications of +the cryptosuite can be found in the specification, here: +[eddsa-jcs-2022](https://www.w3.org/TR/vc-di-eddsa/#eddsa-jcs-2022) + +[[def: Entry Hash, entryHash]] + +~ A `DID:tdw` entry hash is a hash generated using a formally defined process +over the input data to a [[ref: log entry]], excluding the [[ref: Data Integrity]] proof +item. The input data includes content from the predecessor to the version of the +DID, ensuring that all the versions are "chained" together in a microledger. The +generated [[ref: entry hash]] is subsequently included in the `versionId` element of the [[ref: log entry]] and **MUST** be +verified by a resolver. + +[[def: ISO8601, ISO8601 String]] + +~ A date/time expressed using the [ISO8601 +Standard](https://en.wikipedia.org/wiki/ISO_8601). + +[[def: JSON Canonicalization Scheme]] + +~ [[spec:rfc8785]] defines a method for canonicalizing a JSON +structure such that is suitable for verifiable hashing or signing. + +[[def: JSON Lines]] + +~ A file of JSON Lines, as described on the site +[https://jsonlines.org/](https://jsonlines.org/). In short, `JSONL` is lines of JSON with +whitespace removed and separated by a newline that is convenient for handling +streaming JSON data or log files. + +[[def: JSON Patch]] + +~ [[spec:rfc6902]] is a web standard format for describing how to change a JSON +document from one state to another. A [[ref: DID Controller]] **MAY** use it in `DID:tdw` +to define how a [[ref: DIDDoc]] is changed from one version to the next. + +[[def: Pre-Rotation]] + +~ A technique for a controller of a cryptographic key to commit to the public +key it will rotate to next, without exposing that actual public key. It protects +from an attacker that gains knowledge of the current private key from being +able to rotate to a new key known only to the attacker. + +[[def: Linked-VP, Linked Verifiable Presentation]] + +~ A [[spec:DID-CORE]] `service` entry that specifies where a [[ref: verifiable +presentation]] about the DID subject can be found. The [Decentralized Identity +Foundation](https://identity.foundation/) hosts the [Linked VP +Specification](https://identity.foundation/linked-vp/). + +[[def: multihash]] + +~ Per the [[spec:draft-multiformats-multihash-07]], [[ref: multihash]] is a specification +for differentiating instances of hashes. Software creating a hash prefixes +(according to the specification) data to the hash indicating the algorithm used +and the length of the hash, so that software receiving the hash knows how to +verify it. Although [[ref: multihash]] supports many hash algorithms, for +interoperability, [[ref: DID Controllers]] **MUST** only use the hash algorithms defined +in this specification as permitted. + +[[def: multi-sig, multisig]] + +~ A cryptographic signature that to be valid **MUST** contain a defined threshold +(for example, 4 of 7) individual signatures to be considered valid. The +multi-signature key reference points to a verification method that defines what +keys may contribute to the signature, and under what conditions the +multi-signature is considered valid. + +[[def: parameters]] + +~ `DID:tdw` [[ref: parameters]] are a defined set of configurations that control how the +issuer has generated the DID, and how the resolver should process the DID [[ref: Log +entries]]. The use of [[ref: parameters]] allows for the controlled evolution of `DID:tdw` +log handling, such as evolving the permitted hash algorithms. + +[[def: self-certifying identifier, SCID, SCIDs]] + +~ An object identifier derived from initial data such that an attacker could not +create a new object with the same identifier. The input for a `DID:tdw` SCID is +the initial [[ref: DIDDoc]] with the placeholder `{SCID}` wherever the SCID is to be +placed. + +[[def: Verifiable Credential, Verifiable Credentials]] + +~ A verifiable credential can represent all of the same information that a physical credential represents, adding technologies such as digital signatures, to make the credentials more tamper-evident and so more trustworthy than their physical counterparts. The [Verifiable Credential Data Model](https://www.w3.org/TR/vc-data-model/) is a W3C Standard. + +[[def: Verifiable Presentation, Verifiable Presentations]] + +~ A [[ref: verifiable presentation]] data model is part W3C's [Verifiable Credential Data +Model](https://www.w3.org/TR/vc-data-model/) that contains a set of [[ref: +verifiable credentials]] about a `credentialSubject`, and a signature across the +verifiable credentials generated by that subject. In this specification, the use +case of primary interest is where the DID is the `credentialSubject` and the DID +signs the [[ref: verifiable presentation]]. + +[[def: witness, witnesses]] + +~ Witnesses are participants in the process of creating and verifying a version +of a `DID:tdw` [[ref: DIDDoc]]. Notably, a witness receives from the [[ref: DID Controller]] a [[ref: DID +Log]] entry ready for publication, verifies it according to this specification, +and approves it according to its ecosystem governance (whatever that might be). If the verification and +approval process results are positive, witnesses returns to the DID Controller a [[ref: Data Integrity]] proof +attesting to that positive result. + +[[def: W3C VCDM]] + +~ A Verifiable Credential that uses the Data Model defined by the W3C [[spec: W3C-VC]] specification. diff --git a/spec/example.md b/spec/example.md new file mode 100644 index 0000000..db6c913 --- /dev/null +++ b/spec/example.md @@ -0,0 +1,333 @@ +## `did:tdw` Example + +The following shows the evolution of a `did:tdw` from inception through several +versions, showing the DID, [[ref: DIDDoc]], [[ref: DID Log]], and some of the +intermediate data structures. + +**The examples are aligned with version 0.3 of the `did:tdw` specification.** + +In some of the following examples the data for the [[ref: DID log entries]] is displayed +as prettified JSON for readability. In the log itself, the JSON has all +whitespace removed, and each line ends with a `CR`, per the [[ref: JSON Lines]] convention. + +### DID Creation Data + +These examples show the important structures used in the [Create (Register)](#create-register) operation for a `did:tdw` DID. + +#### Input to the SCID Generation Process with Placeholders + +The following JSON is an example of the input that the [[ref: DID Controller]] +constructs and passes into the +[SCID Generation Process](#scid-generation-and-verification). In this example, the [[ref: DIDDoc]] is +particularly boring, containing the absolute minimum for a valid [[ref: DIDDoc]]. + +This example includes both the initial "authorized keys" to sign the [[ref: Data Integrity]] proof +(`updateKeys`) and the [[ref: pre-rotation]] commitment to the next authorization keys (`nextKeyHashes`). Both +are in the `parameters` item in the [[ref: log entry]]. + +```json +[ + "{SCID}", + "2024-07-29T17:00:27Z", + { + "prerotation": true, + "updateKeys": [ + "z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc" + ], + "nextKeyHashes": [ + "QmcbM5bppyT4yyaL35TQQJ2XdSrSNAhH5t6f4ZcuyR4VSv" + ], + "method": "did:tdw:0.3", + "scid": "{SCID}" + }, + { + "value": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/multikey/v1" + ], + "id": "did:tdw:{SCID}:domain.example" + } + } +] +``` + +#### Output of the SCID Generation Process + +After the [[ref: SCID]] is generated, the literal `{SCID}` placeholders are +replaced by the generated [[ref: SCID]] value (below). This JSON is the input to +the [`entryHash` generation process](#entry-hash-generation-and-verification) -- +with the [[ref: SCID]] as the first item of the array. Once the process has run, +the version number of this first version of the DID (`1`), a dash `-` and the +resulting output hash replace the [[ref: SCID]] as the first item in the array +-- the `versionId`. + +```json +[ + "Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu", + "2024-07-29T17:00:27Z", + { + "prerotation": true, + "updateKeys": [ + "z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc" + ], + "nextKeyHashes": [ + "QmcbM5bppyT4yyaL35TQQJ2XdSrSNAhH5t6f4ZcuyR4VSv" + ], + "method": "did:tdw:0.3", + "scid": "Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu" + }, + { + "value": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/multikey/v1" + ], + "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example" + } + } +] +``` + +#### Data Integrity Proof Generation and First Log Entry + +The last step in the creation of the first [[ref: log entry]] is the generation +of the [[ref: data integrity]] proof. One of the keys in the `updateKeys` [[ref: +parameter]] **MUST** be used (in the form of a `did:key`) to generate the +signature in the proof, with the `versionId` value (item 1 of the [[ref: did log +entry]]) used as the `challenge` item. The generated proof is added to the [[ref: JSON +Line]] as the fifth item, and the entire array becomes the first entry in the +[[ref: DID Log]]. + +The following is the JSON prettified version of the entry log file that is published +as the `did.jsonl` file. When published, all extraneous whitespace is removed, as +shown in the block below the pretty-printed version. + +```json +[ + "1-QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ", + "2024-07-29T17:00:27Z", + { + "prerotation": true, + "updateKeys": [ + "z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc" + ], + "nextKeyHashes": [ + "QmcbM5bppyT4yyaL35TQQJ2XdSrSNAhH5t6f4ZcuyR4VSv" + ], + "method": "did:tdw:0.3", + "scid": "Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu" + }, + { + "value": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/multikey/v1" + ], + "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example" + } + }, + [ + { + "type": "DataIntegrityProof", + "cryptosuite": "eddsa-jcs-2022", + "verificationMethod": "did:key:z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc#z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc", + "created": "2024-07-29T17:00:27Z", + "proofPurpose": "authentication", + "challenge": "1-QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ", + "proofValue": "zDk24L4vbVrFm5CPQjRD9KoGFNcV6C3ub1ducPQEvDQ39U68GiofAndGbdG9azV6r78gHr1wKnKNPbMz87xtjZtcq9iwN5hjLptM9Lax4UeMWm9Xz7PP4crToj7sZnvyb3x4" + } + ] +] +``` + +The same content "un-prettified", as it is found in the `did.jsonl` file: + +```json +["1-QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ", "2024-07-29T17:00:27Z", {"prerotation": true, "updateKeys": ["z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc"], "nextKeyHashes": ["QmcbM5bppyT4yyaL35TQQJ2XdSrSNAhH5t6f4ZcuyR4VSv"], "method": "did:tdw:0.3", "scid": "Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu"}, {"value": {"@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/multikey/v1"], "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example"}}, [{"type": "DataIntegrityProof", "cryptosuite": "eddsa-jcs-2022", "verificationMethod": "did:key:z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc#z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc", "created": "2024-07-29T17:00:27Z", "proofPurpose": "authentication", "challenge": "1-QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ", "proofValue": "zDk24L4vbVrFm5CPQjRD9KoGFNcV6C3ub1ducPQEvDQ39U68GiofAndGbdG9azV6r78gHr1wKnKNPbMz87xtjZtcq9iwN5hjLptM9Lax4UeMWm9Xz7PP4crToj7sZnvyb3x4"}]] +``` + +#### `did:web` Version of DIDDoc + +As noted in the [publishing a parallel `did:web` +DID](#publishing-a-parallel-didweb-did) section of this specification a `did:tdw` can be published +by replacing `did:tdw` with `did:web` in the [[ref: DIDDoc]], adding an `alsoKnownAs` entry for the `did:tdw` +and publishing the resulting [[ref: DIDDoc]] at `did.json`, logically beside the `did.jsonl` file. + +Here is what the `did:web` [[ref: DIDDoc]] looks like for the `did:tdw` above. + +```json +{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/multikey/v1" + ], + "id": "did:web:domain.example", + "alsoKnownAs": ["did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example"] +} +``` + +### Version 2 of the DIDDoc + +Time passes, and the [[ref: DID Controller]] of the `did:tdw` DID decides to +update its DID to a new version, version 2. In this case, the only change +the [[ref: DID Controller]] makes is transition the authorization key to +the [[ref: pre-rotation]] key. + +#### Version 2 Entry Hashing Input + +To generate a new version of the DID, the [[ref: DID Controller]] needs to +provide the existing [[ref: DID log]] file, the updated `parameters`, and the new [[ref: DIDDoc]]. +The following processing is done to create the new [[ref: DID log entry]]: + +- The `versionId` from the previous (first) [[ref: log entry]] is made the first item in the new [[ref: log entry]]. +- The `versionTime` is generated as the current time, and made the new `versionTime` (second) item. +- The `parameters` entry passed in is processed. In this case, since the +`updateKeys` array is updated, and [[ref: pre-rotation]] is active, the a +verification is done to ensure that the hash of the `updateKeys` are found in +the `nextKeyHashes` item from version 1 of the DID. As required by the `did:tdw` +specification, a new `nextKeyHashes` is included in the `parameters`. +- The new (but unchanged) [[ref: DIDDoc]] is included in its entirety, as the value of `value`, set as the third item in the array. + - The implementation could have used [[ref: JSON Patch]] to generate value of the `patch` item. +- The resulting array is passed into the [`entryHash` generation + process](#entry-hash-generation-and-verification) which outputs the + `entryHash` for this [[ref: log entry]]. Once again, the first item + (`versionId`) in the [[ref: log entry]] is replaced by the version number (the + previous version number plus `1`), a dash (`-`), and the new `entryHash`. +- The [[ref: data integrity]] proof is generated added to the [[ref: log entry]] + as the sixth item, and the entire entry is added to the existing [[ref: DID + log]]. + +The [[ref: DID log]] file can now be published, optionally with an updated version of the corresponding `did:web` DID. + +The following is the JSON pretty-print [[ref: log entry]] for the second version of an example `did:tdw`. Things to note in this example: + +- The [[ref: data integrity]] proof `verificationMethod` is the `did:key` from the first [[ref: log entry]], and the `challenge` is the `versionId` from this [[ref: log entry]]. +- A new `updateKeys` item in the `parameters` has been added, a commit to a future key that will control updates to the DID. + +```json +[ + "2-QmY2v1VzkeMxF7MSfrLfZswQ74Y6FfrMR1LmuvPJQJwhi6", + "2024-07-29T17:00:28Z", + { + "updateKeys": [ + "z82Lkvgj5NKYhoFh4hWzax9WicQaVDphN8MMzR3JZhontVfHaoGd9JbC4QRpDvmjQH3BLeQ" + ], + "nextKeyHashes": [ + "QmcCbGzGNr2EFduauzCoh3Hwt1GkRW4Gnkk5nxbr3625de" + ] + }, + { + "value": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/multikey/v1" + ], + "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example" + } + }, + [ + { + "type": "DataIntegrityProof", + "cryptosuite": "eddsa-jcs-2022", + "verificationMethod": "did:key:z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc#z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc", + "created": "2024-07-29T17:00:28Z", + "proofPurpose": "authentication", + "challenge": "2-QmY2v1VzkeMxF7MSfrLfZswQ74Y6FfrMR1LmuvPJQJwhi6", + "proofValue": "z2VDUyVapPpb6rC4YbLZRLcWS2zg9o53JU97QjNQYH7JvGs5Ccnf2b647Gw96G5N8rvEKc77uQTGqYvLJ6zrqNwGnqNLraTPD2AL2rR2eUiRKnM5KhbwWumDy5eqmTumm1FWp" + } + ] +] +``` + +#### Log File For Version 2 + +The new version 2 `did.jsonl` file contains two [[ref: entries]], one for each version +of the [[ref: DIDDoc]]. + +```json +["1-QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ", "2024-07-29T17:00:27Z", {"prerotation": true, "updateKeys": ["z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc"], "nextKeyHashes": ["QmcbM5bppyT4yyaL35TQQJ2XdSrSNAhH5t6f4ZcuyR4VSv"], "method": "did:tdw:0.3", "scid": "Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu"}, {"value": {"@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/multikey/v1"], "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example"}}, [{"type": "DataIntegrityProof", "cryptosuite": "eddsa-jcs-2022", "verificationMethod": "did:key:z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc#z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc", "created": "2024-07-29T17:00:27Z", "proofPurpose": "authentication", "challenge": "1-QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ", "proofValue": "zDk24L4vbVrFm5CPQjRD9KoGFNcV6C3ub1ducPQEvDQ39U68GiofAndGbdG9azV6r78gHr1wKnKNPbMz87xtjZtcq9iwN5hjLptM9Lax4UeMWm9Xz7PP4crToj7sZnvyb3x4"}]] +["2-QmY2v1VzkeMxF7MSfrLfZswQ74Y6FfrMR1LmuvPJQJwhi6", "2024-07-29T17:00:28Z", {"updateKeys": ["z82Lkvgj5NKYhoFh4hWzax9WicQaVDphN8MMzR3JZhontVfHaoGd9JbC4QRpDvmjQH3BLeQ"], "nextKeyHashes": ["QmcCbGzGNr2EFduauzCoh3Hwt1GkRW4Gnkk5nxbr3625de"]}, {"value": {"@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/multikey/v1"], "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example"}}, [{"type": "DataIntegrityProof", "cryptosuite": "eddsa-jcs-2022", "verificationMethod": "did:key:z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc#z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc", "created": "2024-07-29T17:00:28Z", "proofPurpose": "authentication", "challenge": "2-QmY2v1VzkeMxF7MSfrLfZswQ74Y6FfrMR1LmuvPJQJwhi6", "proofValue": "z2VDUyVapPpb6rC4YbLZRLcWS2zg9o53JU97QjNQYH7JvGs5Ccnf2b647Gw96G5N8rvEKc77uQTGqYvLJ6zrqNwGnqNLraTPD2AL2rR2eUiRKnM5KhbwWumDy5eqmTumm1FWp"}]] +``` + +#### Log File For Version 3 + +The same process is repeated for version 3 of the DID. In this case: + +- The [[ref: DIDDoc]] is changed, and a patch generated. + - an `authentication` method is added. + - two services are added. +- No changes are made to the authorized keys to update the DID. As a result, the `parameters` entry is empty (`{}`), and the [[ref: parameters]] in effect from previous versions of the DID remain in effect. + +Here is the pretty-printed [[ref: log entry]]: + +```json +[ + "3-QmNwk72WkEjUMQxqkxYoKWNx8Y1pDiGUZCn9PpeLtfPtyk", + "2024-07-29T17:00:28Z", + {}, + { + "patch": [ + { + "op": "add", + "path": "/authentication", + "value": [ + "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#z6Mkq57k27wL26zrxpvGVdEsCKe5kfpJhzy7GciVUfmosTdv" + ] + }, + { + "op": "add", + "path": "/assertionMethod", + "value": [ + "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#z6Mkq57k27wL26zrxpvGVdEsCKe5kfpJhzy7GciVUfmosTdv" + ] + }, + { + "op": "add", + "path": "/service", + "value": [ + { + "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#domain", + "type": "LinkedDomains", + "serviceEndpoint": "https://domain.example" + }, + { + "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#whois", + "type": "LinkedVerifiablePresentation", + "serviceEndpoint": "https://domain.example/.well-known/whois.vc" + } + ] + }, + { + "op": "add", + "path": "/@context/2", + "value": "https://identity.foundation/.well-known/did-configuration/v1" + }, + { + "op": "add", + "path": "/@context/3", + "value": "https://identity.foundation/linked-vp/contexts/v1" + } + ] + }, + [ + { + "type": "DataIntegrityProof", + "cryptosuite": "eddsa-jcs-2022", + "verificationMethod": "did:key:z82Lkvgj5NKYhoFh4hWzax9WicQaVDphN8MMzR3JZhontVfHaoGd9JbC4QRpDvmjQH3BLeQ#z82Lkvgj5NKYhoFh4hWzax9WicQaVDphN8MMzR3JZhontVfHaoGd9JbC4QRpDvmjQH3BLeQ", + "created": "2024-07-29T17:00:28Z", + "proofPurpose": "authentication", + "challenge": "3-QmNwk72WkEjUMQxqkxYoKWNx8Y1pDiGUZCn9PpeLtfPtyk", + "proofValue": "z2TBssHyJj7dB4LDGjHWm3EfHhBiu534w4ucRF95XG3KzLg4m5kjtYbupGmf4txjqQRPko8Qd8PGeHgykWdutHXxJUmvvpGuiJxNBRpfwfKxnsbrT7jWeT6GqaFYqqkDcCG35" + } + ] +] +``` + +Here is the [[ref: log entry]] for just version 3 of the DID. + +```json +["3-QmNwk72WkEjUMQxqkxYoKWNx8Y1pDiGUZCn9PpeLtfPtyk", "2024-07-29T17:00:28Z", {}, {"patch": [{"op": "add", "path": "/authentication", "value": ["did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#z6Mkq57k27wL26zrxpvGVdEsCKe5kfpJhzy7GciVUfmosTdv"]}, {"op": "add", "path": "/assertionMethod", "value": ["did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#z6Mkq57k27wL26zrxpvGVdEsCKe5kfpJhzy7GciVUfmosTdv"]}, {"op": "add", "path": "/service", "value": [{"id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#domain", "type": "LinkedDomains", "serviceEndpoint": "https://domain.example"}, {"id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example#whois", "type": "LinkedVerifiablePresentation", "serviceEndpoint": "https://domain.example/.well-known/whois.vc"}]}, {"op": "add", "path": "/@context/2", "value": "https://identity.foundation/.well-known/did-configuration/v1"}, {"op": "add", "path": "/@context/3", "value": "https://identity.foundation/linked-vp/contexts/v1"}]}, [{"type": "DataIntegrityProof", "cryptosuite": "eddsa-jcs-2022", "verificationMethod": "did:key:z82Lkvgj5NKYhoFh4hWzax9WicQaVDphN8MMzR3JZhontVfHaoGd9JbC4QRpDvmjQH3BLeQ#z82Lkvgj5NKYhoFh4hWzax9WicQaVDphN8MMzR3JZhontVfHaoGd9JbC4QRpDvmjQH3BLeQ", "created": "2024-07-29T17:00:28Z", "proofPurpose": "authentication", "challenge": "3-QmNwk72WkEjUMQxqkxYoKWNx8Y1pDiGUZCn9PpeLtfPtyk", "proofValue": "z2TBssHyJj7dB4LDGjHWm3EfHhBiu534w4ucRF95XG3KzLg4m5kjtYbupGmf4txjqQRPko8Qd8PGeHgykWdutHXxJUmvvpGuiJxNBRpfwfKxnsbrT7jWeT6GqaFYqqkDcCG35"}]] +``` + +And so on... diff --git a/spec/header.md b/spec/header.md new file mode 100644 index 0000000..a4c4744 --- /dev/null +++ b/spec/header.md @@ -0,0 +1,34 @@ +Trust DID Web - `did:tdw` +================== + +**Specification Status:** DRAFT + +**Specification Version:** 0.3 (see [Changelog](#did-tdw-version-changelog)) + +**Latest Draft:** + [https://github.com/decentralized-identity/trustdidweb](https://github.com/decentralized-identity/trustdidweb) + +**Editors:** +~ [Stephen Curran](https://github.com/swcurran) +~ [John Jordan, BC Gov](https://github.com/jljordan42) +~ [Andrew Whitehead](https://github.com/andrewwhitehead) +~ [Brian Richter](https://github.com/brianorwhatever) +~ [Michel Sahli](https://github.com/bj-ms) +~ [Martina Kolpondinos](https://github.com/martipos) +~ [Dmitri Zagdulin](https://github.com/dmitrizagidulin) + +**Participate:** +~ [GitHub repo](https://github.com/decentralized-identity/trustdidweb) +~ [File a bug](https://github.com/decentralized-identity/trustdidweb/issues) +~ [Commit history](https://github.com/decentralized-identity/trustdidweb/commits/main) + +**Implementations:** +~ [TypeScript] +~ [Python] +~ [Go] + +[TypeScript]: https://github.com/bcgov/trustdidweb-ts +[Python]: https://github.com/bcgov/trustdidweb-py +[Go]: https://github.com/nuts-foundation/trustdidweb-go + +------------------------------------ diff --git a/spec/implementors_guide.md b/spec/implementors_guide.md new file mode 100644 index 0000000..e213f4e --- /dev/null +++ b/spec/implementors_guide.md @@ -0,0 +1,248 @@ +## Implementors Guide + +### Implementations + +Proof of concept implementations of `did:tdw` software for [[ref: DID Controllers]] and resolvers can be found here: + +- [Typescript] +- [Python] +- [Go] + +Both currently (as of 2024.04.11) support all of the features of the core `did:tdw` including [[ref: Key Pre-Rotation]]. Not yet supported is the the concept of [[ref: witnesses]]. + +### Using Pre-Rotation Keys + +In an effort to prevent the loss of control over a decentralized identifier +(DID) due to a compromised private key, [[ref: pre-rotation]] keys are +introduced. These commitments, made by the [[ref: DID Controller]], are +declarations about the keys that will be published in future versions of the DID +document, without revealing the keys themselves. + +The primary goal of [[ref: pre-rotation]] keys is to ensure that even if an attacker +gains access to the current active key, they will not be able to take control of +the DID. This safeguard is achieved because the attacker could not simply rotate to +a key they generate and control. Rather, they would need to have also +compromised the unpublished (and presumably securely stored) [[ref: pre-rotation]] key in +order to rotate the DID keys. + +The cost of having [[ref: pre-rotation]] protection is a much more complicated process to update +the keys of a DID. The following are some considerations we have come across in +considering how to use the [[ref: pre-rotation]] feature. The feature definitely adds a +layer of key management complexity in return for the benefit. + +#### Key Rotation with Pre-Rotation + +In using [[ref: pre-rotation]], a [[ref: DID Controller]] should generate an "active" key +for the [[ref: DIDDoc]] where it can be used for "production" purposes (signing, +decrypting), and generates the "next key" in an isolated location from +production. This prevents both the "active" and "next key" from being compromised in the +same attack. For example, an intruder gets into your infrastructure and is able to extract all of your +private keys both DID control keys would be lost. Thus, we expect the feature to be used as follows: + +- The [[ref: DID Controller]] creating the DID would request from an isolated + service the hash of the "next key" as defined in this specification. For + example, an entity might have the "active" DID/key hosted by one Cloud + Provider, and the "next key" by another, on the theory that an attacker might + get into one environment or another but not both. +- When a key rotation is to be done, two [[ref: entries]] are put in the log, using the following steps by the [[ref: DID Controller]]: + 1. Get the full key reference entry from the isolated service for the [[ref: pre-rotation]] "nextKey". + 2. Locally generate a [[ref: pre-rotation]] key hash for a new key that will soon become the "active" key. + 3. Add a [[ref: DID log]] entry that includes the items from the previous two steps, and signs the proof using an authorized key (that presumably it controls, though not required). + 1. Although the [[ref: DID log]] could be published now, it is probably best to hold off and publish it after adding a second, as described by the rest of the steps. + 4. Get a new [[ref: pre-rotation]] hash from the isolated service. + 5. Get the full key-rotation key reference for the [[ref: pre-rotation]] hash created for the last [[ref: DID log entry]]. + 6. Add a [[ref: DID Log]] entry that includes the items from the previous two step + 7. If the key rotated in the previous [[ref: DID log entry]] was a/the + authorized key to make updates to the DID, call the isolated service to produce + the [[ref: Data Integrity]] proof over the entry using the key the isolated + service controls. + 1. This step is not needed if the active service has a key authorized to sign the [[ref: DIDDoc]] update. + 8. Publish the new [[ref: DID log]] containing the two new [[ref: entries]]. + +#### Post Quantum Attacks + +One of the potential benefits of this approach to [[ref: pre-rotation]] is that it is +"post-quantum safe". The idea is that in a post-quantum world, the availability +of the published key and signatures may enable the calculation of the +corresponding private key. Since the [[ref: pre-rotation]] value is a hash of the +`nextKey` and not the public key itself, a post-quantum attack would not +compromise that key, and so a further rotation by the attacker would not be +possible. If there was a (suspected) need to transition to using a quantum-safe +key, the same process listed above would be used, but key reference and the +pre-rotation hash added into the second [[ref: DID log]] entry would presumably +both be for quantum-safe keys. + +#### Challenges in Using Pre-Rotation + +This draft specification states that once [[ref: pre-rotation]] is enabled (via [[ref: +DID log entry]] [[ref: parameter]]), it **MUST** apply to all of the keys in the +DIDDoc. However, we're not sure if that is needed, or if the [[ref: pre-rotation]] should +only apply to keys that are authorized to update the DID. + +Key management is hard enough without having to maintain isolated key generation +environments for creating keys for different purposes. Enabling connectivity between +the key generation environments to enable automated key rotation while maintaining the +key recovery environment as "isolated" is technically challenging. + +### Using DID Portability + +As noted in the [DID Portability](#did-portability) section of the +specification, a `did:tdw` DID can be renamed (ported) by changing the `id` DID string in +the [[ref: DIDDoc]] to one that resolves to a different HTTPS URL, as long as the +specified conditions are met. + +While the impact of the feature is in fact the creation of a new DID, we think +there is significant value in some use cases for supporting the specified +capability. Ideally, the HTTPS URL for the "old" DID is changed to a redirect to +the new DID, allowing for a seamless, verifiable evolution of the DID. + +An interesting example use case is a DID that replaces an email address hosted +by a particular service. The extra capabilities of having the identifier being a +DID vs. an email address is compelling enough, allowing it to be used for a +range of services beyond email. The [[ref: portability]] benefit comes when the owner of +the DID decides to move to a new service, taking their DID with them. The +verifiable history carried over to the renamed DID hosted by the new service +provides assurance to those who interacted with the old DID (through chats, +emails, postings, etc.) that they are still engaging with the same entity, +despite the DID renaming. Compare that with what happens today when you switch +from one email provider to another, and you have to reach out to all your +contacts to assure them that you changed providers. + +While [[ref: portability]] is powerful, it must be used with care and only in use +cases where the capability is specifically required. When used, both the +pre-rotation and [[ref: witnesses]] features of `did:tdw` **SHOULD** also be enabled. + +#### Mergers, Acquisitions and Name Changes + +Organizations change over time and such changes often involve names changes. +Name changes in turn trigger domain name changes, as organizations match their +Web location with their names. Mergers, acquisitions, and simple name changes, +all can cause an organization's "known" domain name to change, including the +relinquishment of control over their previous domain name. When such changes +occur, it is very unlikely that just because the organization's DIDs use the old +domain name will prevent the changes. Thus the DIDs need to "adapt" to the new +domain -- the domain name portion of the DID has to change. Ideally, the old +location and domain can be retained and a web redirect used to resolve the old +DID to the new, but even if that cannot be done, the ability to use the same +SCID and retain the full history can be preserved. + +#### DID Hosting Service Providers + +Consider being able to replace the current identifiers we are given (email +addresses, phone numbers) with `did:tdw` DIDs. Comparable hosting platforms +might publish our DIDs for us (ideally, with us in custody of our own private +keys...). Those DIDs, with the inherent public keys can be used for many +purposes -- encrypted email (hello PGP!), messaging, secure file sharing, and +more. + +From time to time in that imagined future, we may want to move our DIDs +from one hosting service to another, just as we move from one email or mobile +provider to another. With DIDs that can move and retain the history, we can make +such moves smoothly. Contacts will see the change, but also see that the history +of the DID remains. + +#### Challenges in Moving a DID + +While we see great value (and even a hard requirement) for being able to move a +DID's web location, it does create challenges in aligning with the +[[spec:DID-CORE]] specification. These challenges are listed below. + +Moving a `did:tdw` is actually the (partial or complete) deactivation of the old +DID and the creation of a new DID. The use of the [[ref: SCID]] and the way it +is generated is designed to prevent an attacker from being able to create a DID +they control but with the same [[ref: SCID]] as existing DID. Thus, "finding" a `did:tdw` +with the same [[ref: SCID]] implies the DIDs are the same. That can be verified by +processing the [[ref: DID Log]]. + +By retaining the incrementing of the `versionId` after a move, the "new" DID +does not start at `versionId` of `1`. Further, resolving `?versionId=1` +is going to return a [[ref: DIDDoc]] with the top-level `id` equal to the ``. +This is useful from a business perspective, but unexpected from a +[[spec:DID-CORE]] perspective. + +### Using High Assurance DIDs with DNS + +The [High Assurance DIDs with DNS] mechanism that can be used with `did:web` +applies equally well with `did:tdw`. A [[ref: DID Controller]] publishing a +`did:tdw` could use the mechanisms defined in the [High Assurance DIDs with DNS] +specification despite `did:tdw` DIDs not (yet) being explicitly called out in +the [High Assurance DIDs with DNS] specification. In particular, as `did:tdw` +uses the same DID-to-HTTP transformation, publishing the expected DNS Domain +records, and adding the required verification method and [[ref: Data Integrity]] +proof to their [[ref: DIDDoc]] is done as defined in the [High Assurance DIDs +with DNS] specification. Likewise, a resolver can include code to check to see if +the [[ref: DID Controller]] published the [High Assurance DIDs with DNS] +specification DNS records and use those to further verify the DID. + +Alternatively, since `did:tdw` is not mentioned in the [High Assurance DIDs with +DNS] specification, a `did:tdw` [[ref: DID Controller]] could use the "not `did:web`" +technique described in that specification and include a `dnsValidationDomain` +entry in the [[ref: DIDDoc]] to explicitly denote where to find the DNS records to use in +binding the DID to the DNS domain. This technique could also be used with +`did:tdw` (and `did:web` for that matter) if the DID is published on a platform +(such as GitHub) and the controller wants to bind it to its DNS domain. + +#### Future Possibilities + +In the future, as `did:tdw` becomes more accepted, we would like to see +`did:tdw` explicitly added to the [High Assurance DIDs with DNS] specification +beside `did:web`. + +Since `did:tdw` and the [High Assurance DIDs with DNS] specification both have +the goal of adding methods for additional verifications of the DID, the support +for `did:tdw` in the [High Assurance DIDs with DNS] could be more specific to +the DID Method. For example, the key in the DNS record could be a required +`did:tdw` witness, with its [[ref: Data Integrity]] proof being a part of the +[[ref: DID log entry]] rather than in the [[ref: DIDDoc]] itself. + +### Witnesses + +The term "witness" is often used in the decentralized trust space to refer to +participants in an ecosystem that oversee the evolution of an identifier +according to some ecosystem-specific governance framework. The goal is for a +[[ref: witness]] to collect, verify and approve data about the identifier and +share it with others that trust the [[ref: witness]] so they don't need to do +that work themselves. The extra participants are intended to identify both +malicious attackers of the identifier, and malicious use of the identifier by +the [[ref: DID Controller]]. + +Witnesses play an explicit function in `did:tdw`. When used by a [[ref: DID +Controller]], [[ref: witnesses]] (themselves identified by DIDs) are sent +pending [[ref: DID log entries]] prepared by the [[ref: DID Controller]]. The +[[ref: witnesses]] verify the [[ref: log entry]] using their copy of the +"current state" of the DID, and then "approve" the update, according to the +governance they use to define what "approval" means. For example, a [[ref: +witness]] might interact with another party (perhaps even a person) to confirm +that the [[ref: DID Controller]] created the [[ref: log entry]]. Once the [[ref: +witness]] has both verified and approved the change, they express that approval +by creating a [[ref: Data Integrity]] proof that is chained to the [[ref: data +integrity]] proof created by the [[ref: DID Controller]], and send the proof +back to the [[ref: DID Controller]]. Once the number of [[ref: data integrity]] +proofs received by the [[ref: DID Controller]] from the [[ref: witnesses]] has +exceeded a threshold, the [[ref: DID Controller]] adds those proofs to their own +[[ref: data integrity]] proof in the [[ref: log entry]]. Next, the [[ref: DID +Controller]] adds the [[ref: log entry]] to the [[ref: DID log]] and publishes +the updated DIDDoc. A [[ref: DID Controller]] relying on [[ref: witnesses]] +cannot independently publish an update to their DID -- they must get and publish +the [[ref: witness]] approval proofs. + +The application of [[ref: witnesses]] is very much dependent on the governance +of the ecosystem. Such governance is outside the scope of the `did:tdw` +specification, and up to those deploying `did:tdw` DIDs. Hence, a [[ref: DID +Controller]] that controls a series of DIDs and uses those DIDs as [[ref: +witnesses]] adds no additional trust or security to a DID if no properly defined +governance is in place. In particular, in order for [[ref: witnesses]] to add +security and trust to a DID requires the members of an ecosystem to agree to the +defined governance. A [[ref: witness]] could be an "endorser" of a set of DIDs +that are part of an ecosystem, with the act of witnessing the updates conveying +through their approval that the DIDs are a legitimate participant in the +ecosystem. [[ref: Witnesses]] can also be used as a form of "two-factor +authentication" of a change, such as having a public key published as a DNS +record used as a [[ref: witness]] for the DID. Such an addition means that an +attacker would need to compromise both the web-publishing infrastructure of the +DID Controller (where they publish the DID's `did.jsonl` file) as well as its +DNS entry. + +`did:tdw` witnesses have been specified to be simple to implement and use. Their +power and effectiveness will come in how they are deployed within specific, +governed ecosystems. diff --git a/spec/overview.md b/spec/overview.md new file mode 100644 index 0000000..1a377ce --- /dev/null +++ b/spec/overview.md @@ -0,0 +1,189 @@ +## Overview + +The emergence of [[ref: Decentralized Identifiers]] (DIDs) and with them the +evolution of [[ref: DID Methods]] continues to be a dynamic area of +development in the quest for trusted, secure and private digital identity +management where the users are in control of their own data. + +The `did:web` method, for example, leverages the Domain Name System (DNS) to +perform the DID operations. This approach is praised for its simplicity and +ease of deployment, including DID-to-HTTPS transformation and addressing +some aspects of trust by allowing for DIDs to be associated with a domain's +reputation or published on platforms such as GitHub. However, it is not +without its challenges-- +from trust layers inherited from the web and the absence of a verifiable +history for the DID. + +Tackling these concerns, the proposed `did:tdw` (Trust DID Web) +method aims to enhance `did:web` by introducing additional features such +as a [[ref: self-certifying identifier]] (SCID), update key(s) +and a verifiable history, akin to what is available with ledger-based DIDs, +without relying on a ledger. + +This approach not only maintains backward compatibility but also offers an +additional layer of assurance for those requiring more robust verification +processes. By publishing the resulting DID as both `did:web` and `did:tdw`, it +caters to a broader range of trust requirements, from those who are comfortable +with the existing `did:web` infrastructure to those seeking greater security +assurances provided by `did:tdw`. This innovative step represents a significant +stride towards a more trusted and secure web, where the integrity of +cryptographic key publishing is paramount. + +The key differences between `did:web` and `did:tdw` revolve around the core +issues of decentralization and security. `did:web` is recognized for its +simplicity and cost-effectiveness, allowing for easy establishment of a +credential ecosystem. However, it is not inherently decentralized as it relies +on DNS domain names, which require centralized registries. Furthermore, it lacks a +cryptographically verifiable, tamper-resistant, and persistently stored DID +document. In contrast, `did:tdw` (Trust DID Web) is proposed as an enhancement +to `did:web`, aiming to address these limitations by adding a verifiable history +to the DID without the need for a ledger. This method seeks to provide a more +decentralized approach by ensuring that the security of the embedded +SCID does not depend on DNS. Additionally, `did:tdw` is +capable of resolving a cryptographically verifiable trust registry and status +lists, using DID-Linked Resources, which `did:web` lacks. These features are +designed to build a trusted web, offering a higher level of assurance for +cryptographic key publishing and management. + +For backwards compatibility, and for verifiers that "trust" `did:web`, a +`did:tdw` can be trivially modified and published in parallel to a `did:web` +DID. For resolvers that want more assurance, `did:tdw` provides a way to "trust +did:web" (or to enable a "trusted web" if you say it fast) enabled by the +features listed in the [Abstract](#abstract). + +The following is a `tl;dr` summary of how `did:tdw` works: + +1. `did:tdw` uses the same DID-to-HTTPS transformation as `did:web`, so + `did:tdw`'s `did.jsonl` ([[ref: JSON Lines]]) file is found in the same + location as `did:web`'s `did.json` file, and supports an easy transition + from `did:web` to gain the added benefits of `did:tdw`. +2. The `did.jsonl` is a list of JSON [[ref: DID log entries]], one per line, + whitespace removed (per [[ref: JSON Lines]]). Each entry contains the + information needed to derive a version of the [[ref: DIDDoc]] from its preceding + version. The `did.jsonl` is also referred to as the [[ref: DID Log]]. +3. Each [[ref: DID log entry]] includes a JSON array of five items: + 1. The `versionId` of the entry, a value that combines the version number + (starting at `1` and incrementing by one per version), a literal dash + `-`, and a hash of the entry. The [[ref: entry hash]] calculation links each entry + to its predecessor in a ledger-like chain. + 2. The `versionTime` (as stated by the [[ref: DID Controller]]) of the entry. + 3. A set of `parameters` that impact the processing of the current and + future [[ref: log entries]]. + - Example [[ref: parameters]] are the version of the `did:tdw` specification and + hash algorithm being used as well as the [[ref: SCID]] and update key(s). + 4. The new version of the [[ref: DIDDoc]] as either a `value` (the full document) or + a `patch` derived using [[ref: JSON Patch]] to update the new version from + the previous entry. + 5. A [[ref: Data Integrity]] (DI) proof across the entry, signed by a [[ref: DID + Controller]] authorized to update the [[ref: DIDDoc]], using the `versionId` as the + challenge. +4. In generating the first version of the [[ref: DIDDoc]], the [[ref: DID Controller]] calculates + the [[ref: SCID]] for the DID from the entire first [[ref: log entry]] (which + includes the [[ref: DIDDoc]]) by adding the string {SCID} everywhere the actual [[ref: SCID]] + is to be placed. The [[ref: DID Controller]] then replaces these placeholders + with the just calculated [[ref: SCID]], including it as a `parameter` in the first [[ref: log + entry]], and inserting it where needed in the initial (and all subsequent) + DIDDocs. The [[ref: SCID]] enables an optional [[ref: portability]] capability, allowing a DID's + web location to be moved to a new location while retaining the DID and version + history of the DID. +5. A [[ref: DID Controller]] generates and publishes the new/updated [[ref: DID Log]] file by making it + available at the appropriate location on the web, based on the identifier of the + DID. +6. Given a `did:tdw` DID, a resolver converts the DID to an HTTPS URL, + retrieves, and processes the [[ref: DID Log]] `did.jsonl`, generating and verifying + each [[ref: log entry]] as per the requirements outlined in this specification. + - In the process, the resolver collects all the [[ref: DIDDoc]] versions and public + keys used by the DID currently, or in the past. This enables + resolving both current and past versions of the DID. +7. `did:tdw` DID URLs with paths and `/whois` are resolved to documents + published by the [[ref: DID Controller]] that are by default in the web location relative to the + `did.jsonl` file. See the [note below](#the-whois-use-case) about the + powerful capability enabled by the `/whois` DID URL path. +8. Optionally, a [[ref: DID Controller]] can easily generate and publish a `did:web` DIDDoc + from the latest `did:tdw` [[ref: DIDDoc]] in parallel with the `did:tdw` [[ref: DID Log]]. + + ::: warning + A resolver settling for just the `did:web` version of the DID does not get the + verifiability of the `did:tdw` log. + ::: + +An example of a `did:tdw` evolving through a series of versions can be seen in +the [did:tdw Examples](#didtdw-example) of this specification. + +This draft specification was developed in parallel with the development of two +proof of concept implementations. The specification/implementation interplay +helped immensely in defining a practical, intuitive, straightforward, DID +method. The existing proof of concept implementations of the `did:tdw` DID +Method are listed in the [Implementors Guide](#Implementations). The current +implementations range from around 1500 to 2000 lines of code. + +### The `/whois` Use Case + +This DID Method introduces what we hope will be a widely embraced convention for +all [[ref: DID Methods]] -- the `/whois` path. This feature harkens back to the `WHOIS` +protocol that was created in the 1970s to provide a directory about people and +entities in the early days of ARPANET. In the 80's, `whois` evolved into +[[spec-inform:rfc920]] that has expanded into the [global +whois](https://en.wikipedia.org/wiki/WHOIS) feature we know today as +[[spec-inform:rfc3912]]. Submit a `whois` request about a domain name, and get +back the information published about that domain. + +We propose that the `/whois` path for a DID enable a comparable, decentralized, +version of the `WHOIS` protocol for DIDs. Notably, when `/whois` is +resolved (using a standard DID `service` that follows the [[ref: Linked-VP]] +specification), a [[ref: Verifiable Presentation]] (VP) may be returned (if +published by the [[ref: DID Controller]]) containing [[ref: Verifiable Credentials]] with +the DID as the `credentialSubject`, and the VP signed by the DID. Given a DID, +one can gather verifiable data about the [[ref: DID Controller]] by resolving +`/whois` and processing the returned VP. That's powerful -- an efficient, +highly decentralized, trust registry. For `did:tdw`, the approach is very simple +-- transform the DID to its HTTPS equivalent, and execute a `GET /whois`. +Need to know who issued the VCs in the VP? Get the issuer DIDs from those VCs, +and resolve `/whois` for each. This is comparable to walking a CA +(Certificate Authority) hierarchy, but self-managed by the [[ref: DID Controllers]] -- +and the issuers that attest to them. + +The following is a use case for the `/whois` capability. Consider an example of +the `did:tdw` controller being a mining company that has exported a shipment and +created a "Product Passport" Verifiable Credential with information about the +shipment. A country importing the shipment (the Importer) might want to know +more about the issuer of the VC, and hence, the details of the shipment. They +resolve the `/whois` of the entity and get back a Verifiable Presentation +about that DID. It might contain: + +- A verifiable credential issued by the Legal Entity Registrar for the + jurisdiction in which the mining company is headquartered. + - Since the Importer knows about the Legal Entity Registrar, they can automate + this lookup to get more information about the company from the VC -- its + legal name, when it was registered, contact information, etc. +- A verifiable credential for a "Mining Permit" issued by the mining authority + for the jurisdiction in which the company operates. + - Perhaps the Importer does not know about the mining authority for that + jurisdiction. The Importer can repeat the `/whois` resolution process for + the issuer of _that_ credential. The Importer might (for example), resolve + and verify the `did:tdw` DID for the Authority, and then resolve the + `/whois` DID URL to find a verifiable credential issued by the government of + the jurisdiction. The Importer recognizes and trusts that government's + authority, and so can decide to recognize and trust the mining permit + authority. +- A verifiable credential about the auditing of the mining practices of the + mining company. Again, the Importer doesn't know about the issuer of the audit + VC, so they resolve the `/whois` for the DID of the issuer, get its VP and + find that it is accredited to audit mining companies by the [London Metal + Exchange](https://www.lme.com/en/) according to one of its mining standards. + As the Importer knows about both the London Metal Exchange and the standard, + it can make a trust decision about the original Product Passport Verifiable + Credential. + +Such checks can all be done with a handful of HTTPS requests and the processing +of the DIDs and verifiable presentations. If the system cannot automatically +make a trust decision, lots of information has been quickly collected that can +be passed to a person to make such a decision. + +The result is an efficient, verifiable, credential-based, decentralized, +multi-domain trust registry, empowering individuals and organizations to verify +the authenticity and legitimacy of DIDs. The convention promotes a decentralized +trust model where trust is established through cryptographic verification rather +than reliance on centralized authorities. By enabling anyone to access and +validate the information associated with a DID, the "/whois" path contributes to +the overall security and integrity of decentralized networks. diff --git a/spec/references.md b/spec/references.md new file mode 100644 index 0000000..7b30615 --- /dev/null +++ b/spec/references.md @@ -0,0 +1,3 @@ +## References + +[[spec]] diff --git a/spec/security_and_privacy.md b/spec/security_and_privacy.md new file mode 100644 index 0000000..6ab2f33 --- /dev/null +++ b/spec/security_and_privacy.md @@ -0,0 +1,42 @@ +## Security and Privacy Considerations + +### DNS Considerations + +#### DNS Security Considerations + +Implementers must secure DNS resolution to protect against attacks like Man in +the Middle, following the detailed guidance in the [did:web +specification](https://w3c-ccg.github.io/did-method-web/#dns-considerations). +The use of DNSSEC [[spec:RFC4033]], [[spec:RFC4034]], [[spec:RFC4035]] is +essential to prevent spoofing and ensure authenticity of DNS records. + +#### DNS Privacy Considerations + +Resolving a `did:tdw` identifier can expose users to tracking by DNS providers +and web servers. To mitigate this risk, it's recommended to use privacy-enhancing +technologies such as VPNs, TOR, or trusted universal resolver services, in line +with strategies outlined in the [did:web +specification](https://w3c-ccg.github.io/did-method-web/#dns-considerations) +including emerging RFCs such as [Oblivious DNS over +HTTPS](https://datatracker.ietf.org/doc/html/draft-pauly-dprive-oblivious-doh-03) +for DNS privacy. + +### In-transit Security + +For in-transit security, the guidance provided in the [did:web +specification](https://w3c-ccg.github.io/did-method-web/#in-transit-security) +regarding the encryption of traffic between the server and client should be +followed. + +### International Domain Names + +[[spec:DID-CORE]] identifier syntax does not allow Unicode in method name nor +method specific identifiers. + +Implementers should be cautious when implementing support for DID URLs that rely +on domain names or path components that contain Unicode characters. + +See also: + +- [UTS-46](https://unicode.org/reports/tr46/) +- [[spec:RFC5895]] diff --git a/spec/specification.md b/spec/specification.md new file mode 100644 index 0000000..a9c22a2 --- /dev/null +++ b/spec/specification.md @@ -0,0 +1,1184 @@ +## did:tdw DID Method Specification + +### Target System + +The target system of the Trust DID Web (TDW) DID method is the host (or domain) +name when the domain specified by the DID is resolved through the Domain Name +System (DNS) and verified by processing a log of DID versions. + +### Method Name + +The namestring that identifies this DID method is: `tdw`. A DID that uses this +method MUST begin with the following prefix: `did:tdw`. Per the DID +specification, this string MUST be in lowercase. The remainder of the DID, after +the prefix, is the [method-specific identifier](#method-specific-identifier), +specified below. + +### Method-Specific Identifier + +The `did:tdw` method-specific identifier contains both the [[ref: +self-certifying identifier]] (SCID) for the DID, and a fully qualified domain +name (with an optional path) that is secured by a TLS/SSL certificate. Given the +DID, a [transformation to an HTTPS URL](#the-did-to-https-transformation) can be +performed such that the [[ref: DID Log]] for the `did:tdw` DID is retrieved (via +an `HTTP GET`) and processed to produce the [[ref: DIDDoc]] for the DID. As per the +Augmented Backus-Naur Form (ABNF) notation below, the [[ref: SCID]] **MUST** be the first element of +the method-specific identifier. + +Formal rules describing valid domain name syntax are described in +[[spec:RFC1035]], [[spec:RFC1123]], and [[spec:RFC2181]]. Each `did:tdw` DID's +globally unique [[ref: SCID]] is [generated](#scid-generation-and-verification) +during the creation of the DID based on its initial content and placed into +the DID identifier for publication and use. + +The domain name element of the method-specific identifier MUST match the +common name used in the SSL/TLS certificate, and it MUST NOT include IP +addresses. A port MAY be included and the colon MUST be percent encoded to +prevent a conflict with paths. Directories and subdirectories MAY optionally be +included, delimited by colons rather than slashes. + +As specified in the following Augmented Backus-Naur Form (ABNF) notation +[[spec:rfc2234]] the [[ref: SCID]] **MUST** be present in the DID string. See +examples below. The `domain-segment` and `path-segment` elements refer to +[[spec:rfc3986]]'s ABNF for a Generic URL (page 49). Attempting to replicate +here the full ABNF of those elements from that RFC would inevitably be wrong. + +```abnf +tdw-did = "did:tdw:" scid ":" domain-segment 1+( "." domain-segment ) *( ":" path-segment ) +domain-segment = ; A part of a domain name as defined in RFC3986, such as "example" and "com" in "example.com" +path-segment= ; A part of a URL path as defined in RFC3986, such as "path", "to", "folder" in "path/to/folder" +``` + +The ABNF for a `did:tdw` is almost identical to that of `did:web`, with changes only to +the DID Method (`tdw` instead of `web`), and the addition of the `:` +element in `did:tdw` that is not in `did:web`. As specified in the [DID-to-HTTPS +Transformation](#the-did-to-https-transformation) section of this specification, +`did:tdw` and `did:web` DIDs that have the same fully qualified domain and path +transform to the same HTTPS URL, with the exception of the final file -- +`did.json` for `did:web` and `did.jsonl` for `did:tdw`. + +### The DID to HTTPS Transformation + +The `did:tdw` [method-specific identifier](#method-specific-identifier) is +defined to enable a transformation of the DID to an HTTPS URL for publishing +and retrieving the [[ref: DID Log]]. This section defines the transformation +from DID to HTTPS URL, including a number of examples. + +Given a `did:tdw`, the HTTPS URL for the [[ref: DID Log]] is generated by +carrying out the following steps. The steps are carried out by the [[ref: DID +Controller]] to determine where to publish the [[ref: DID Log]], and by all resolvers to +retrieve the [[ref: DID Log]]. + +1. Remove the literal `did:tdw:` prefix from the DID, leaving the method specific + identifier. +2. Remove the [[ref: SCID]] by removing the text up to and including the first colon + (`:`) from the method-specific identifier and continue processing. +3. Replace `:` with `/` in the method-specific identifier to obtain the fully + qualified domain name and optional path. +4. If there is no optional path, append `/.well-known` to the URL. + 1. When this algorithm is used for resolving a DID path (such as + `/whois` or `/path/to/file as defined in the section [DID URL + Handling](#did-url-resolution)), the `/.well-known` **MUST NOT** be + included in the HTTPS URL. +5. If the domain contains a port, percent decode the colon. +6. Generate an HTTPS URL to the expected location of the [[ref: DIDDoc]] by prepending + `https://`. +7. Append `/did.jsonl` to complete the URL. + 1. When this algorithm is used for resolving a DID path (such as + `/whois` or `/path/to/file as defined in the section [DID URL + Handling](#did-url-resolution)), append the DID URL path instead. + +The following are some examples of various DID-to-HTTPS transformations based +on the processing steps specified above. + +::: example + +`did:tdw` DIDs and the corresponding web locations of their `did:tdw` log file. +In the examples,`{SCID}` is a placeholder for where the generated [[ref: SCID]] would be +placed in the actual DIDs and HTTPS URLs. Note that when the `{SCID}` follows +the literal `did:tdw:` as a separate element, the `{SCID}` is not part of the +HTTPS URL. + +--- + +domain/`did:web`-compatible + +`did:tdw:{SCID}:example.com` --> + +`https://example.com/.well-known/did.jsonl` + +subdomain + +`did:tdw:{SCID}:issuer.example.com` --> + +`https://issuer.example.com/.well-known/did.jsonl` + +path + +`did:tdw:{SCID}:example.com:dids:issuer` --> + +`https://example.com/dids/issuer/did.jsonl` + +path w/ port + +`did:tdw:{SCID}:example.com%3A3000:dids:issuer` --> + +`https://example.com:3000/dids/issuer/did.jsonl` + +::: + +The location of the `did:tdw` `did.jsonl` [[ref:DID Log]] file is the same as +where the comparable `did:web` `did.json` file is published. A [[ref: DID +Controller]] **MAY** choose to publish both DIDs and so, both files. The process +to do so is described in the [publishing a parallel `did:web` +DID](#publishing-a-parallel-didweb-did) section of this specification. + +### The DID Log File + +The [[ref: DID log]] file contains a list of [[ref: entries]], one for each version of the DID. A +version of the DID is an update to the contents of the resolved [[ref: DIDDoc]] for the +DID, and/or a change to the [[ref: parameters]] that control the generation and +verification of the DID. + +Each entry is a JSON array consisting of the following 5 items. + +`[ versionId, versionTime, parameters, DIDDoc State, Data Integrity Proof ]` + +1. The entry `versionId` is a value that combines the version number (starting at + `1` and incrementing by one per DID version), a literal dash `-`, and the + `entryHash`, a hash calculated across the [[ref: log entry]] content. The input to the + hash is chosen so as to link each entry to its predecessor in a ledger-like + chain. The input to the hash is specified in the [Entry Hash Generation and + Verification](#entry-hash-generation-and-verification) section of this + specification. +2. The `versionTime` (as stated by the [[ref: DID Controller]]) of the entry, in [[ref: ISO8601]] format. +3. A JSON object `parameters` that define configurations/options used in the + processing of current and future [[ref: log entries]]. `parameters` are defined in the + [`did:tdw` DID Method Parameters](#didtdw-did-method-parameters) section of + this specification. +4. The `DIDDoc State` for this version of the DID as either `value`, the full + [[ref: DIDDoc]], or `patch`, such that the new [[ref: DIDDoc]] is derived using + [[ref: JSON Patch]] from the previous entry. +5. A `Data Integrity Proof` across the entry, signed by a [[ref: DID + Controller]] authorized to update the [[ref: DIDDoc]], using the `versionId` as the + challenge. + +After creation, each entry has (per the [[ref JSON Lines]] specification) all +extra whitespace removed, a `\n` character appended, and the result added to +the [[ref: DID Log]] file for publication. + +A more comprehensive description of how to create a [[ref: DID log entry]] and update it +into a [[ref: JSON Line]] is given in steps 4 - 6 of the next section. + +Examples of [[ref: DID Logs]] and [[ref: DID log entries]] can be found in the +[did:tdw` Examples](#didtdw-example) section of this specification. + +### DID Method Operations + +#### Create (Register) + +Creating a `did:tdw` DID is done by carrying out the following steps. + +1. **Define the DID string** + The start of the DID **MUST** be the literal string "`did:tdw:{SCID}:`", where the `{SCID}` is + a placeholder that will be replaced by the calculated [[ref: SCID]] later in the process (see step + 5). This first part of the DID string is followed by a fully qualified domain name + (with an optional path) that is secured by a TLS/SSL certificate and + reflects the web location at which the [[ref: DID Log]] (`did.jsonl`) will be published + + The DID **MUST** be a valid `did:tdw` DID as per the ABNF of a `did:tdw` DID defined + in the [Method-Specific Identifier](#method-specific-identifier) section of this specification. + + 1. Note: the [[ref: SCID]] for a `did:tdw` DID is not by default in the HTTPS URL for the DID. + A [[ref: DID Controller]] that wants to include the [[ref: SCID]] in the HTTPS URL **MAY** + add additional placeholder `{SCID}` strings into the domain name or path + components of the method-specific identifier when creating the DID. The + additional instance(s) of the [[ref: SCID]] have no impact on the handling of the + DID, and are treated like any other part of the domain and/or path. + +2. **Generate the authorization key pair(s)** + [Authorized keys](#authorized-keys) are authorized to control (create, update, deactivate) the DID. + This includes generating any other key pairs that will be placed into the initial + [[ref: DIDDoc]] for the DID. + + 1. If the DID is to use [[ref: pre-rotation]], additional key generation will + be necessary to generate the required "next" authorization keys and their + corresponding [[ref: pre-rotation]] hashes. + 2. For each authorization key pair, generate a [[ref: multikey]] based on the + key pair's public key. The [[ref: multikey]] representations of the public + keys are placed in the `updateKeys` item in [[ref: parameters]]. + 3. The public key(s) of the authorization key pair(s) **MAY** be used in the + [[ref: DIDDoc]] as well, but that is not required. + +3. **Create the initial [[ref: DIDDoc]] for the DID** + The [[ref: DIDDoc]] **MUST** contain the top level `id` item which **MUST** be the DID string from + step 1, including the placement of the `{SICD}` placeholder for the [[ref: SCID]]. Other + [[ref: DIDDoc]] verifications **SHOULD** be performed. + + All other absolute self-reference's to the DID in the [[ref: DIDDoc]] must use the form defined + in step 1, with the identified placeholder for the [[ref: SCID]] (e.g., `did:tdw:{SCID}:example.com#key-1`, + `did:tdw:{SCID}:example.com:dids:issuer#key-1`, etc.). The [[ref: DIDDoc]] can contain any other content as deemed necessary by the [[ref: DID Controller]]. + + 1. Note: The placeholder (the string `{SCID}`) **MUST** be in every place in the [[ref: DIDDoc]] where + the [[ref: SCID]] is to be placed. + +4. **Generate a preliminary DID Log Entry** (input JSON array) + The [[ref: DID log entry]] is an input JSON array that when completed contains the following items: + `[ versionId, versionTime, parameters, DIDDoc State, Data Integrity Proof ]`. When creating + (registering) the DID the first entry starts with the follows items for processing: + `[ "{SCID}", "", "parameters": [ ], { "value": "" } ]` + + 1. **Add a preliminary `versionId` value** + The first item in the input JSON array **MUST** be the placeholder string `{SCID}`. + 2. **Add the `versionTime` value** + The second item in the input JSON array **MUST** be a valid [[ref: ISO8601]] date/time string, + and that the represented time **MUST** be before or equal to the current time. + 3. **Define the [[ref: parameters]]** + The third item in the input JSON array **MUST** be the [[ref: parameters]] + JSON object. The [[ref: parameters]] are used to configure the DID generation and verification + processes. All [[ref: parameters]] **MUST** be valid and all required values in the first version + of the DID **MUST** be present. + + The [DID Generation and Verification Parameters](#didtdw-did-method-parameters) + section of this specification defines the permitted [[ref: parameters]]. That + section defines what items **MUST** be included in this first [[ref: log entry]] for the DID. + Collect and use the specified [[ref: parameters]] in the remainder of the DID creation steps. + + 4. **Add the initial [[ref: DIDDoc]]** + The fourth item in the input JSON array **MUST** be the JSON object `{"value": }`, + where `` is the initial [[ref: DIDDoc]] as described in the previous step 3. + +5. **Update the preliminary DID Log Entry to the initial DID Log Entry** + Use the preliminary [[ref: DID log entry]] to perform the consecutive steps: + + 1. **Calculate the [[ref: SCID]]** + The input JSON array **MUST** be used to calculate the [[ref: SCID]] for the DID as defined in + the [SCID Generation and Verification](#scid-generation-and-verification) section of this + specification. + 2. **Replace the placeholder `{SCID}`** + Replace throughout the input JSON array the placeholder "`{SCID}`" for the [[ref: SCID]] with + the calculated [[ref: SCID]] from the previous step. + 3. **Calculate the [[ref: Entry Hash]]** + The JSON array updated in the previous step **MUST** be used to calculate the [[ref: Entry Hash]] + (`entryHash`) for the [[ref: log entry]], as defined in the + [Entry Hash Generation and Verification](#entry-hash-generation-and-verification) section of + this specification. + 4. **Replace the preliminary `versionId` value** + The value of the `versionId` (first) item of the JSON array **MUST** be updated with the + literal string `1-` (for version number 1) followed by the `entryHash` value produced in the previous step. + 5. **Generate the [[ref: Data Integrity]] proof** + A [[ref: Data Integrity]] proof on the initial [[ref: DIDDoc]] **MUST** be generated + using an authorized key from a DID in the required `updateKeys` item in the [[ref: parameters]], + and the `versionId` as the proof `challenge`. + + If the [[ref: DID Controller]] has opted to use [[ref: witnesses]] for the DID, the required approvals + from the DID's [[ref: witnesses]] **MUST** be collected and added to the + [[ref: Data Integrity]] proof item. See the [DID Witnesses](#did-witnesses) section of this specification. + + 6. **Add the [[ref: Data Integrity]] proof** + The fifth item in the input JSON array **MUST** be added to the JSON array. The result is in the + initial [[ref: DID log entry]] for the DID. + +6. **Generate the first [[ref: JSON Line]]** + The [[ref: DID log entry]] **MUST** be updated to be a [[ref: JSON Lines]] + entry by removing extraneous white space and appending a carriage return, + and stored as the contents of the file `did.jsonl`. + +7. **Publish the [[ref: DID Log]]** + The complete [[ref: DID Log]] file **MUST** be published at the appropriate Web location defined by + the `did:tdw` DID identifier (see step 1) + - This is a logical operation -- how a deployment serves the `did.jsonl` + content is not constrained. + - Use the [DID-to-HTTPS Transformation](#the-did-to-https-transformation) + steps to transform the DID into the Web location of the [[ref: DID Log]] + file. + +A controller **MAY** generate an equivalent `did:web` [[ref: DIDDoc]] and publish it as +defined in the +[Publishing a Parallel `did:web` DID](#publishing-a-parallel-didweb-did) section +of this specification. The `did:web` [[ref: DIDDoc]] could be used for backwards +compatibility as a transition is made from `did:web` to `did:tdw`. Verifiers +using the `did:web` lose the verifiable properties and history of the `did:tdw` +for the convenience of the simple retrieval of the `did:web` [[ref: DIDDoc]]. + +#### Read (Resolve) + +The following steps MUST be executed to resolve the [[ref: DIDDoc]] for a `did:tdw` DID: + +1. The [DID-to-HTTPS Transformation](#the-did-to-https-transformation) steps + **MUST** be used to transform the DID into an HTTPS URL for the [[ref: DID + Log]] file. +2. Perform an HTTPS `GET` request to the URL using an agent that can successfully + negotiate a secure HTTPS connection, which enforces the security requirements + as described in + [Security and privacy considerations](#security-and-privacy-considerations). +3. When performing the DNS resolution during the HTTPS GET request, the client + SHOULD utilize [[spec:rfc8484]] in order to prevent tracking of the identity + being resolved. +4. The [[ref: DID Log]] file **MUST** be processed as described below. + +To process the retrieved [[ref: DID Log]] file, the resolver **MUST** carry out +the following steps on each of the [[ref: log entries]] in the order they appear in the +file, applying the [[ref: parameters]] set from the current and previous +entries. As noted in the [DID Log File](#the-did-log-file) section, log entries +are each a JSON array with five items: + + 1. `versionId` + 2. `versionTime` + 3. `parameters` + 4. `DIDDoc State` -- either the full `value` or a [[ref: JSON Patch]] `patch` + to be applied to the prior version of the [[ref: DIDDoc]]. + 5. A [[ref: Data Integrity]] proof array for the version of the [[ref: DIDDoc]] corresponding to that + entry. + +For each entry: + +1. Update the currently active [[ref: parameters]] with the [[ref: parameters]] from + the entry (if any). Continue processing using the now active set of + [[ref: parameters]]. + - While all [[ref: parameters]] in the first [[ref: Log Entry]] take effect + immediately, some kinds of [[ref: parameters]] defined in later [[ref: entries]] only take + effect *after* that entry has been published. For example, rotating the + authorized keys to update a DID takes effect only *after* the entry in + which they are defined has been published. +2. The [[ref: Data Integrity]] proof in the entry **MUST** be valid and signed by + an authorized key as defined in the [Authorized Keys](#authorized-keys) + section of this specification. + 1. If the [[ref: DID Controller]] has opted to use [[ref: witnesses]] and the + last entry of the log is being processed, the [[ref: witness]] [[ref: Data + Integrity]] proofs **MUST** be valid and **MUST** be signed by a threshold + of [[ref: witnesses]]. For details, see the [DID + Witnesses](#did-witnesses) section of this specification. +3. Verify the `versionId` for the entry. Recall the the `versionId` is the + concatenation of the version number, a dash (`-`), and the `entryHash`. + 1. The version number **MUST** be `1` for the the first [[ref: log entry]] and **MUST** be + incremented by one for each subsequent [[ref: log entry]]. + 2. A dash `-` **MUST** follow the version number. + 3. The `entryHash` **MUST** follow the dash, and **MUST** be verified using + the process defined in the [Entry Hash Generation and + Verification](#entry-hash-generation-and-verification) section of this + specification. +4. The `versionTime` **MUST** be a valid [[ref: ISO8601]] date/time string. The + `versionTime` for each [[ref: log entry]] **MUST** be greater than the + previous entry's time. The `versionTime` of the last entry **MUST** be + earlier than the current time. +5. Parse and apply the `did:tdw` DID Method configuration `parameters`. Note + that in versions after the first, some `parameters` apply to immediately and + impact the process of the current DID version, while others, such as + `updateKeys` and `witnesses` apply after the current version has been + published. The `parameters` **MUST** adhere to the [`did:tdw` DID Method + Parameters](#didtdw-did-method-parameters) section of this specification. +6. When processing the first [[ref: DID log]] entry, verify the [[ref: SCID]] + (defined in the [[ref: parameters]]) according to the + [SCID Generation and Verification](#scid-generation-and-verification) section + of this specification. +7. Extract the contents of the [[ref: DIDDoc]] for each entry by using the JSON value + of the `value` item, or by using [[ref: JSON Patch]] to apply the JSON + value of the `patch` entry item to the previous version of the [[ref: DIDDoc]]. +8. If [[ref: Key Pre-Rotation]] is being used, the hash of all `updateKeys` entries + in the `parameters` item **MUST** match a hash in + the active array of `nextKeyHashes` [[ref: parameter]], as defined in the + [Key [[ref: Pre-Rotation]] Hash Generation and Verification](#pre-rotation-key-hash-generation-and-verification) + section of this specification. +9. If any verifications fail, discard the DID as invalid with an error message. +10. As each [[ref: log entry]] is processed and verified, collect the following information + about each version: + 1. The [[ref: DIDDoc]]. + 2. The `versionId` of the [[ref: DIDDoc]]. + 3. The `versionTime`of the [[ref: DIDDoc]]. + 4. The latest list of active [[ref: multikey]] formatted public keys + authorized to update the DID, from the `updateKeys` lists in the + [[ref: parameters]]. + 5. If [[ref: pre-rotation]] is being used, the hashes of authorized DIDs that may + be used in later `updateKeys` lists. The [[ref: pre-rotation]] hashes are in the + `nextKeyHashes` list in the [[ref: parameters]]. + 6. All other `did:tdw` processing configuration settings as defined by in the + `parameters` object. + +On completing the processing and successful verification of all [[ref: entries]] in the +[[ref: DID Log]], respond to the DID resolution request, including the +application of DID query [[ref: parameters]] such as `?versionId=` and `?versionTime=` with +the appropriate [[ref: DIDDoc]] version and content. + +The following error codes and descriptions may be returned when resolving a DID. + +:::todo + +Document the full list of error codes that can be generated in resolving a DID. + +::: + +- Code 404: The `did:tdw` [[ref: DID Log]] file `did.jsonl` was not found. + +##### Reading did:tdw DID URLs + +A `did:tdw` resolver **MAY** implement the resolution of the `/whois` and a DID +URL Path using the [whois LinkedVP Service](#whois-linkedvp-service) and +[DID URL Path Resolution Service](#did-url-path-resolution-service) as defined in +this specification by processing the [[ref: DID Log]] and then dereferencing the +DID URL based on the contents of the [[ref: DIDDoc]]. The client of a resolver that does +not implement those capabilities must use the resolver to resolve the +appropriate [[ref: DIDDoc]], and then process the resulting DID URLs themselves. Since +the default DID-to-HTTPS URL transformation is trivial, `did:tdw` +[[ref: DID Controllers]] are strongly encouraged to use the default behavior +for DID URL Path resolution. + +#### Update (Rotate) + +To update a DID, a new, verifiable [[ref: DID Log Entry]] must be generated, +witnessed (if necessary), appended to the existing [[ref: DID Log]] (`did.jsonl`), +and published to the web location defined by the DID. The process to generate a +verifiable [[ref: DID Log Entry]] follows a similar process to the +[Create](#create-register) process, as follows: + +1. Make the desired changes to the [[ref: DIDDoc]]. While the contents of a new DIDDoc + version are (mostly) up to the [[ref: DID controller]], there are some limitations: + 1. If the DID is configured to support [[ref: portability]], the root `id` + item in the [[ref: DIDDoc]] **MAY** be changed when the [[ref: DID Controller]] wants to (or + is forced to) publish the DID at a different Internet location and wants + to retain the [[ref: SCID]] and history of the DID. For details, see the + [DID Portability](#did-portability) section of this specification. +2. Define a JSON array of [[ref: parameters]] that affect the evolution of the + DID. The `parameters` **MUST** be from those listed in the [`did:tdw` DID + Method Parameters](#didtdw-did-method-parameters) section of this + specification. Any [[ref: parameters]] defined in the array override the + previously active value, while any [[ref: parameters]] not included imply the + existing values remain in effect. If no changes to the [[ref: parameters]] + are needed, an empty JSON object `{}` **MUST** be used. + - While all [[ref: parameters]] in the first [[ref: Log Entry]] take effect + immediately, some types of [[ref: parameters]] defined in later [[ref: entries]] only take + effect after the entry has been published. For example, rotating the keys + authorized to update a DID or changing the [[ref: witnesses]] for a DID take effect + only *after* the entry in which they are defined has been published. +3. Generate a preliminary [[ref: DID Log Entry]] JSON array with the following JSON items: + 1. The `versionId` **MUST** be `versionId` value from the previous [[ref: DID Log Entry]]. + 2. The `versionTime` value **MUST** be an [[ref: ISO8601]] format time. The time + **MUST** be greater than the time of the previous [[ref: log entry]], and **MUST** be less + than or equal to the current time. + 3. The [[ref: parameters]] passed in as a JSON object. + 4. Generate a [[ref: JSON Patch]] to evolve the previous [[ref: DIDDoc]] version to + the new [[ref: DIDDoc]] version, and put the resulting patch in the item as + `{"patch": }`. For details of the process, see the + [Generating and Applying a JSON Patch](#generating-and-applying-a-json-patch) + section of this specification. + 1. An implementation **MAY** skip the [[ref: JSON Patch]] process and + simply put the full new version of the [[ref: DIDDoc]] in the item + `{"value": }` as is done in the initial entry in the log. +4. Calculate the new `versionId` of the new [[ref: DID Log Entry]], including + incrementing the version number integer and using the process described in + the [Entry Hash Generation and Verification](#entry-hash-generation-and-verification) + section of this specification. +5. Replace the value of the `versionId` item in the preliminary [[ref: DID Log + Entry]] with the value produced in the previous step. +6. Generate a [[ref: Data Integrity]] proof on the new [[ref: DIDDoc]] of the entry + using an authorized key, and the `versionId` as the proof + `challenge`. The definition of "authorized" is formalized in the + [Authorized Keys](#authorized-keys) section of this specification. +7. If the [[ref: DID Controller]] has opted to use [[ref: witnesses]] for the + DID, collect the required approvals from the DID's [[ref: witnesses]], adding + their proofs to the [[ref: data integrity]] proof. See the [DID + Witnesses](#did-witnesses) section of this specification. +8. The proof array **MUST** be added as the fifth and last JSON item in the [[ref: log entry]]. +9. The entry **MUST** be made a [[ref JSON Line]] by removing extra whitespace, adding a `\n` + to the entry. +10. The new [[ref: log entry]] **MUST** be appended to the existing contents of + the [[ref: DID Log]] file `did.jsonl`. +11. The updated [[ref: DID Log]] file **MUST** be published the appropriate + location defined by the `did:tdw` identifier. + - This is a logical operation -- how a deployment serves the `did.jsonl` + content is not constrained. + +A controller **MAY** generate an equivalent, updated `did:web` [[ref: DIDDoc]] and +publish it as defined in the +[Publishing a Parallel `did:web` DID](#publishing-a-parallel-didweb-did) +section of this specification. + +#### Deactivate (Revoke) + +To deactivate the DID, the [[ref: DID Controller]] **SHOULD** add to the [[ref: +DID log entry]] [[ref: parameters]] the item `"deactivated": true`. A [[ref: DID +Controller]] **MAY** update the [[ref: DIDDoc]] further to indicate the deactivation of +the DID, such as including an empty `updateKeys` list (`"updateKeys": []`) in +the [[ref: parameters]], preventing further versions of the DID. + +A resolver encountering in the [[ref: DID log entry]] [[ref: parameters]] the +item `"deactivated": true` **MUST** return in the [[ref: DIDDoc]] Metadata the JSON item +`"deactivated": true`, as per the [[spec:DID-RESOLUTION]] specification. + +### DID Method Processes + +The [DID Method Operations](#did-method-operations) reference several processes +that are executed during [[ref: DIDDoc]] generation and DID resolution verification. Each +of those processes is specified in the following sections. + +#### `did:tdw` DID Method Parameters + +Entries in the `did:tdw` [[ref: DID Log]] file contain, in the 3rd item, a JSON +object that defines the DID processing [[ref: parameters]] being used by the [[ref: DID +Controller]] when publishing that and subsequent [[ref: DID log entries]]. A DID Resolver +will use the same [[ref: parameters]] when processing the [[ref: DID Log]] to resolve the +DID. The [[ref: parameters]] object **MUST** include only the items defined in this +specification. + +::: example + +An example of the JSON prettified [[ref: parameters]] item in the first [[ref: DID Log]] entry for a DID: + +``` json +{ + "prerotation": true, + "portable": false, + "updateKeys": [ + "z82LkqR25TU88tztBEiFydNf4fUPn8oWBANckcmuqgonz9TAbK9a7WGQ5dm7jyqyRMpaRAe" + ], + "nextKeyHashes": [ + "enkkrohe5ccxyc7zghic6qux5inyzthg2tqka4b57kvtorysc3aa" + ], + "method": "did:tdw:0.3", + "scid": "{SCID}" +} +``` + +::: + +The allowed [[ref: parameter]] items and (where applicable) enumerated values for those +items are defined below. + +- `method`: Defines the `did:tdw` specification version to use when processing a + given DID's log file. As new versions of this specifications are + defined, additional [[ref: parameters]] and enumerated values will be added to this. This + allows a long lasting DID to evolve the settings being used by the DID over time, + such as changing the hash algorithm used, or the [[ref: Data Integrity]] cryptosuite. + - This item **MUST** appear in the first [[ref: DID log entry]]. + - This item **MAY** appear in later [[ref: DID log entries]] to indicate that + the processing rules for that and later [[ref: entries]] have been changed to a + different specification version. + - Acceptable values for this specification are: + - `did:tdw:0.3`: Requires that the rules defined in this specification be used + in processing the log. Implied by the value are the following: + - The permitted hash algorithms used by the [[ref: DID Controller]] **MUST** be `SHA-256` as defined in [[spec: rfc6234]]. + - The permitted [[ref: Data Integrity]] cryptosuites used by the [[ref: DID Controller]] **MUST** be `eddsa-jcs-2022` as referenced in [[ref: eddsa-jcs-2022]]. +- `scid`: The value of the [[ref: SCID]] for this DID. + - This item **MUST** appear in the first [[ref: DID log entry]]. +- `updateKeys`: A list of one or more [[ref: multikey]] formatted public keys + associated with the private keys that are authorized to sign the log entries + that update the DID from one version to the next. An instance of the list in + an entry replaces the previously active list. If an entry does not have the + `updateKeys` item, the currently active list continues to apply. See the + [Authorized Keys](#authorized-keys) section of this specification for + additional details. + - This item **MUST** appear in the first [[ref: DID log entry]]. + - A key from the `updateKeys` item in the first [[ref: DID log entry]] + **MUST** be used to authorize the initial [[ref: log entry]]. In all other + [[ref: DID log entries]], an `updateKeys` item becomes active *after* the + publication of its entry -- meaning its [[ref: log entry]] **MUST** be + signed by a key the most recent `updateKeys` list from a **prior** [[ref: + DID log]] entry. +- `portable`: A boolean (`true` / `false`) indicating if the DID is portable and + thus can be renamed to change the Web location of the DID. + - The value can **ONLY** be set to `true` in the first [[ref: log entry]], the initial version of the DID. + - If not explicitly set in the first [[ref: log entry]], it is set to `false`. + - Once the value has been set to `false`, it cannot be set back to `true`. + - See the section of this specification on [DID Portability](#did-portability) + for more details about renaming a `did:tdw` DID. +- `prerotation`: A boolean value indicating that subsequent authentication keys + added to the [[ref: DIDDoc]] (after this version) **MUST** have their hash included in + a `nextKeyHashes` [[ref: parameter]] item. + - The value is initialized to `false` until the item is included in a + [[ref: DID log entry]]. + - Once the value is set to `true` in a [[ref: DID log entry]] it **MUST NOT** + be set to `false` in a subsequent entry. +- `nextKeyHashes`: An array of strings that are hashes of [[ref: multikey]] + formatted public keys that **MAY** be added to the `updateKeys` list in the + [[ref: log entry]] of a future version of the DID. + - The process for generating the hashes and additional details for using [[ref: pre-rotation]] are defined in the + [Pre-Rotation Key Hash Generation and Verification](#pre-rotation-key-hash-generation-and-verification) + section of this specification. + - If the [[ref: parameter]] `prerotation` has been set to `true`, all [[ref: multikey]] + formatted public keys added in a new `updateKeys` list **MUST** have their + hashes listed in the currently active `nextKeyHashes` list. + - A [[ref: DID Controller]] **MAY** put extra strings in the `nextKeyHashes` + item that are not subsequently used in an `updateKeys` entry. + - When `prerotation` is active and the `updateKeys` [[ref: parameter]] is included in a + [[ref: parameters]] item, a `nextKeyHashes` item with a new set of hashes + **MUST** be included in the same [[ref: parameters]] item. Any unused + hashes in the prior `nextKeyHashes` are ignored. +- `witness`: A JSON object containing the [[ref: parameters]] for declaring the witnesses + for the DID, and the [[ref: parameters]] for the process of updating a DID via a + collaboration with [[ref: witnesses]] prior to publication. For details of + this item data and its usage in the approvals process, see the + [DID Witnesses](#did-witnesses) section of this specification. + - A `witness` item in the first [[ref: DID log entry]] is used to define the + [[ref: witnesses]] and necessary threshold for that initial [[ref: log entry]]. In all other + [[ref: DID log entries]], a `witness` item becomes active **after** the publication + of its entry -- meaning its [[ref: log entry]] **MUST** be witnessed by the most recent + `witnesses` from a **prior** [[ref: DID log]] entry. +- `deactivated`: A JSON boolean that **SHOULD** be set to `true` when the DID is to + be deactivated. See the [deactivate (revoke)](#deactivate-revoke) section of + this specification for more details. +- `ttl`: A number, the number of seconds that a cache entry for a resolved + `did:tdw` DID **SHOULD** last, as recommended by the [[ref: DID Controller]]. A + resolver can use this value in deciding whether to retrieve a new version of + the DID's `did.jsonl` file. If not specified, resolvers **MAY** set a default + based on the business needs of the resolver clients. + - Caching a `did:tdw` can be valuable in places where the business rules + require resolving a number of DID URLs for the same DID. For example, a + client might want call the resolver to the current [[ref: DIDDoc]], and then make + repeated calls to get all of the previous versions of the [[ref: DIDDoc]]. By caching + the [[ref: DIDDoc]] state, the resolver would not have to retrieve and process the + [[ref: DID Log]] on each call. + - A Web Server handling one or more `did.jsonl` files **MAY** be configured to + use a comparable HTTP TTL per [[spec-inform:rfc9111]]. + +#### SCID Generation and Verification + +The [[ref: self-certifying identifier]] or `SCID` is a required [[ref: parameter]] in the +first [[ref: DID log entry]] and is the hash of the DID's inception event. + +##### Generate SCID + +To generate the required [[ref: SCID]] for a `did:tdw` DID, the DID Controller +**MUST** execute the following function: + + `base58btc(multihash(JCS(preliminary log entry with placeholders), ))` + +Where: + +1. The `preliminary [[ref: log entry]] with placeholders` consists of the following + pre-publication JSON array of what will become the first [[ref: log entry]]. The + placeholder is the literal string "`{SCID}`". + + - The `versionId` entry, which **MUST** be `{SCID}`. + - The `versionTime` entry, which **MUST** be a string that is the current time in + [[ref: ISO8601]] format, e.g., `"2024-04-05T07:32:58Z"` + - The complete `parameters` for the initial [[ref: log entry]] as defined by the + [[ref: DID Controller]], with the placeholder wherever the [[ref: SCID]] will + eventually be placed. + - The `{"value": }` element with placeholders wherever the [[ref: SCID]] will + eventually be placed in the [[ref: DIDDoc]]. + +2. `JCS` is an implementation of the [[ref: JSON Canonicalization Scheme]] + [[spec:rfc8785]]. It outputs a canonicalized representation of its JSON + input. +3. `multihash` is an implementation of the [[ref: multihash]] specification. Its + output is a hash of the input using the associated ``, + prefixed with a hash algorithm identifier and the hash size. +4. `` is the hash algorithm used by the [[ref: DID Controller]]. + The hash algorithm **MUST** be one listed in the + [parameters](#didtdw-did-method-parameters) defined by the version of the + `did:tdw` specification being used by the [[ref: DID Controller]]. +5. `base58btc` is an implementation of the [[ref: base58btc]] function. + Its output is the base58 encoded string of its input. + +##### Verify SCID + +To verify the [[ref: SCID]] of a `did:tdw` DID being resolved, the resolver +**MUST** execute the following process: + +1. Extract the first [[ref: DID log entry]] and use it for the rest of the steps + in this process. +2. Extract the `scid` item value from the [[ref: parameters]] in the [[ref: DID log entry]]. +3. Determine the hash algorithm used by the [[ref: DID Controller]] from the [[ref: multihash]] `scid` value. + - The hash algorithm **MUST** be one listed in the + [parameters](#didtdw-did-method-parameters) defined by the version of the + `did:tdw` specification being used by the [[ref: DID Controller]] based on the + `method` [[ref: parameters]] item. +4. Remove the [[ref: data integrity]] proof item from the first [[ref: DID log entry]]. +5. Replace the `versionId` item's value with the literal `"{SCID}"`. +6. Treat the resulting [[ref: log entry]] as a string and do a text replacement of the `scid` + value from Step 2 with the literal string `{SCID}`. +7. Use the result and the hash algorithm (from Step 3) as input to the function + defined in the [Generate SCID](#generate-scid) section (above). +8. The output string **MUST** match the `scid` extracted + in Step 2. If not, terminate the resolution process with an error. + +#### Entry Hash Generation and Verification + +The `entryHash` follows the version number and dash character `-` in the +`versionId` item in each DID log entry. Each `entryHash` is calculated +across its [[ref: log entry]], excluding the [[ref: Data Integrity]] proof. The +`versionId` used in the input to the hash is a predecessor value to the current +[[ref: log entry]], ensuring that the [[ref: entries]] are cryptographically "chained" +together in a microledger. For the first [[ref: log entry]], the predecessor +`versionId` is the SCID (itself a hash), while for all other entries it is the +`versionId` item from the previous log entry. + +##### Generate Entry Hash + +To generate the required hash for a `did:tdw` [[ref: log entry]], the [[ref: DID Controller]] +**MUST** execute the process `base58btc(multihash(JCS(entry), ))` given a +preliminary [[ref: log entry]] as the string `entry`, where: + +1. `JCS` is an implementation of the [[ref: JSON Canonicalization Scheme]] + ([[spec:rfc8785]]). Its output is a canonicalized representation of its + input. +2. `multihash` is an implementation of the [[ref: multihash]] specification. Its + output is a hash of the input using the associated ``, + prefixed with a hash algorithm identifier and the hash size. +3. `` is the hash algorithm used by the [[ref: DID Controller]]. + The hash algorithm **MUST** be one listed in the + [parameters](#didtdw-did-method-parameters) defined by the version of the + `did:tdw` specification being used by the [[ref: DID Controller]]. +4. `base58btc` is an implementation of the [[ref: base58btc]] function. + Its output is the base58 encoded string of its input. + +The following is an example of a preliminary [[ref: log entry]] that is processed to +produce an [[ref: entry hash]]. As this is a first entry in a [[ref: DID Log]], the input +`entryHash` (first item) is the [[ref: SCID]] of the DID. + +```json +["Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu", "2024-07-29T17:00:27Z", {"prerotation": true, "updateKeys": ["z82LkvR3CBNkb9tUVps4GhGpNvEVP6vWzdwgGwQbA1iYoZwd7m1F1hSvkJFSe6sWci7JiXc"], "nextKeyHashes": ["QmcbM5bppyT4yyaL35TQQJ2XdSrSNAhH5t6f4ZcuyR4VSv"], "method": "did:tdw:0.3", "scid": "Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu"}, {"value": {"@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/multikey/v1"], "id": "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example"}}] +``` + +Resulting [[ref: entry hash]]: `QmdwvukAYUU6VYwqM4jQbSiKk1ctg12j5hMTY6EfbbkyEJ` + +##### Verify The Entry Hash + +To verify the `entryHash` for a given `did:tdw` [[ref: DID log entry]], a DID +Resolver **MUST** execute the following process: + +1. Extract the `versionId` (first item) in the [[ref: DID log entry]], and + remove from it the version number and dash prefix, leaving the log entry + `entryHash`. +2. Determine the hash algorithm used by the [[ref: DID Controller]] from the [[ref: multihash]] `entryHash` value. + - The hash algorithm **MUST** be one listed in the + [parameters](#didtdw-did-method-parameters) defined by the version of the + `did:tdw` specification being used by the [[ref: DID Controller]] based on the + `method` [[ref: parameters]] item set in the current or most recent prior [[ref: log entry]]. +3. Remove the [[ref: Data Integrity]] proof (5th item) from the [[ref: log entry]]. +4. Set the first item of the entry to the `versionId` (first item) of the + previous [[ref: log entry]]. If this is the first entry in the log, set the value to + the ``, the [[ref: SCID]] of the DID. +5. Calculate the hash string as `base58btc(multihash(JCS(entry), ))`, where: + 1. `entry` is the data from the previous step. + 2. `JCS` is an implementation of the [[ref: JSON Canonicalization Scheme]] + ([[spec:rfc8785]]). Its output is a canonicalized representation of its + input. + 3. `multihash` is an implementation of the [[ref: multihash]] specification. + Its output is a hash of the input using the associated ``, + prefixed with a hash algorithm identifier and the hash size. + 4. `` is the hash algorithm from Step 2. + 5. `base58btc` is an implementation of the [[ref: base58btc]] function. + Its output is the base58 encoded string of its input. +6. Verify that the calculated value matches the extracted `entryHash` value from + Step 1. If not, terminate the resolution process with an error. + +#### Authorized Keys + +Each entry in the [[ref: DID Log]] **MUST** include a [[ref: Data Integrity]] +proof signed by a key **authorized** to control (create, update, deactivate) the +DID. The authorized verification keys for `did:tdw` are the [[ref: multikey]]-formatted +public keys in the **active** `updateKeys` list from the `parameters` item of +the [[ref: log entries]]. Any of the authorized verification keys may be referenced +in the [[ref: Data Integrity]] proof. + +For the first [[ref: log entry]] the **active** `updateKeys` list is the one in +that first [[ref: log entry]]. For all subsequent [[ref: entries]], the **active** list +is the most recent `updateKeys` **before** the [[ref: log entry]] to be verified. Thus, +the general case is that each [[ref: log entry]] is signed by the keys from the +**previous** [[ref: log entry]]. Once a [[ref: log entry]] containing an `updateKeys` list is +published, that `updateKeys` becomes the active list, and the previous +`updateKeys` are ignored. + +A resolver of the DID **MUST** verify the signature and that the key used for +signing each [[ref: DID Log]] entry is one from the list of active `updateKeys`. +If not, terminate the resolution process with an error. + +The `did:tdw` Implementation Guide contains further discussion on the management +of keys authorized to update the DID. + +#### Generating and Applying a JSON Patch + +Each time a new `did:tdw` version is created, the [[ref: DID Controller]] +**MAY** generate a [[ref: JSON Patch]] to concisely define the changes in the +DIDDoc from the previous version. A [[ref: DID log entry]] that uses [[ref: JSON Patch]] +has a JSON object with a `patch` property, with the value the [[ref: +JSON Patch]] as its `DIDDoc State` (fourth) item. A [[ref: DID Controller]] **MAY** set the +`DIDDoc State` item of a [[ref: DID log entry]] to be the JSON item `value`, with its +value the complete [[ref: DIDDoc]]. Typically (but not required), a [[ref: DID Controller]] +will use `value` for the first [[ref: DID log entry]] and `patch` for all +subsequent [[ref: entries]]. + +To create the value for a `patch` item for a [[ref: DID log entry]], the [[ref: +DID Controller]] **MUST**: + +1. Have the fully resolved previous version of the [[ref: DIDDoc]]. +2. Have the updated new version of the [[ref: DIDDoc]] to be added. +3. Execute an implementation of [[ref: JSON Patch]] that takes the two DIDDocs + as inputs (previous before, new after) and outputs the resulting [[ref: JSON Patch]] + from before to after. +4. Set the `DIDDoc State` (fourth) item of the [[ref: DID log entry]] to `{"patch": ""}`, + where `` is the output of the previous step. + +When processing a [[ref: DID log entry]] with a `patch` as the fourth item, a +resolver **MUST**: + +1. Have the fully resolved previous version of the [[ref: DIDDoc]]. +2. Extract the value of the `DIDDoc State` (fourth) item of the [[ref: DID log entry]] `patch` value. + 1. If the `DIDDoc State` item is `value`, its value is the [[ref: DIDDoc]], and the + next step is not needed. +3. Execute an implementation of [[ref: JSON Patch]] that takes the previous + [[ref: DIDDoc]] and the extracted `patch` value as inputs, and outputs the + resulting new version of the [[ref: DIDDoc]]. + +The output is the [[ref: DIDDoc]] for that version of the DID. + +#### DID Portability + +As noted in the [Update (rotate)](#update-rotate) section of the specification, +a `did:tdw` DID can be renamed by changing the `id` DID string in the +DIDDoc to one that resolves to a different HTTPS URL if the following conditions are met. + +- The [[ref: DID Log]] of the renamed DID **MUST** contain all of the [[ref: log + entries]] from the creation of the DID. +- The [[ref: log entry]] in which the DID is renamed **MUST** be a valid DID entry + building on the prior [[ref: DID log entries]], per this specification. +- The [[ref: parameter]] `portable` **MUST** be set to `true`, as defined in the + [DID Method Parameters](#didtdw-did-method-parameters) section. +- The [[ref: SCID]] **MUST** be the same in the original and renamed DID. +- The [[ref: DIDDoc]] **MUST** contain the prior DID string as an `alsoKnownAs` entry. + +#### Pre-Rotation Key Hash Generation and Verification + +Pre-rotation requires a [[ref: DID Controller]] to commit to the authorization +keys that will later be used ("rotated to") for updating the [[ref: DIDDoc]]. The purpose +of committing to future keys is that if the currently authorized keys are +compromised by an attacker, the attacker should not be able to take control of +the DID by using the compromised keys to rotate to new keys the attacker +controls. Assuming the attacker has not also compromised the committed key +pairs, they cannot rotate the authorization keys without detection. See the +non-normative section about [Using [[ref: Pre-Rotation]] Keys](#using-pre-rotation-keys) +in the Implementer's Guide for additional guidance. + +As described in the [parameters](#didtdw-did-method-parameters) +section of this specification, a [[ref: DID Controller]] **MAY** define that +`prerotation` is active for the DID (value `true`). When [[ref: pre-rotation]] is active, +all verification [[ref: multikeys]] in the `updateKeys` [[ref: parameters]] item in other +than the initial version of the [[ref: DIDDoc]] **MUST** have their hash in the currently +active nextKeyHashes` arrays from a previous [[ref: DID log entry]]. If +not, terminate the resolution process with an error. + +To create a hash to be included in the `nextKeyHashes` array, the [[ref: DID +Controller]] **MUST** execute the following process for each possible future +authorization key. + +1. Generate a new key pair. +2. Generate a [[ref: multikeys]] representation of the public key of the new key + pair. +3. Calculate the hash string as `base58btc(multihash(multikey))`, where: + 1. `multikey` is the [[ref: multikey]] representation of the public key from Step 2. + 2. `multihash` is an implementation of the [[ref: multihash]] specification. + Its output is a hash of the input using the associated ``, + prefixed with a hash algorithm identifier and the hash size. + 3. `` is the hash algorithm used by the [[ref: DID Controller]]. + The hash algorithm **MUST** be one listed in the + [parameters](#didtdw-did-method-parameters) defined by the version of the + `did:tdw` specification being used by the [[ref: DID Controller]]. + 4. `base58btc` is an implementation of the [[ref: base58btc]] function. + Its output is the base58 encoded string of its input. +4. Insert the calculated hash into the `nextKeyHashes` array being built up within + the [[ref: parameters]] item. +5. The generated key pair **SHOULD** be safely stored so that it can be used in + a later DID version to become a DID authorization key. At that time, the + [[ref: multikey]] representation of the public key will be inserted into the + `updateKeys` item in the [[ref: parameters]]. After that [[ref: log entry]] is + published, the private key can be used to sign DID update authorizations + proofs. + +A [[ref: DID Controller]] **MAY** add extra hashes (for keys or just random +strings) into a `nextKeyHashes` array. + +When processing other than the first [[ref: DID log entry]] where the +`prerotation` [[ref: parameter]] is active, a `did:tdw` resolver **MUST**: + +1. For each [[ref: multikey]] in the `updateKeys` item in the `parameters` of + the [[ref: log entry]], calculate the hash and hash algorithm for the [[ref: + mulithash]] [[ref: multikey]]. +2. The hash algorithm **MUST** be one listed in the + [parameters](#didtdw-did-method-parameters) defined by the version of the + `did:tdw` specification being used by the [[ref: DID Controller]]. +3. The resultant hash **MUST** in the most recently set `nextKeyHashes` prior to + the [[ref: log entry]] being processed. If not, terminate the resolution + process with an error. +4. A new `nextKeyHashes` list **MUST** be in the `parameters` of the [[ref: log + entry]] currently being processed. If not, terminate the resolution process with + an error. + +#### DID Witnesses + +The [[ref: witness]] process for a DID provides a way for other collaborators to +work with the [[ref: DID Controller]] to "witness" the publication of a new version of +the DID. Including [[ref: witnesses]] can prevent malicious updates to the DID by both +the [[ref: DID Controller]] and external parties. This specification defines +the mechanism for using [[ref: witnesses]] but leaves the governance and policy +questions about when and how to use the mechanism to implementers. + +Witnesses can prevent a [[ref: DID Controller]] from updating/removing DID versions of a +DID without detection. [[ref: Witnesses]] are also a further mitigation against malicious +actors compromising both a [[ref: DID Controller]]'s authorization key(s) to update the +DID, and the [[ref: DID Controller]]'s web site where the [[ref: DID log]] is published. +With both compromises, a malicious actor could take control over the DID by +rewriting the [[ref: DID Log]] using the keys they have comprised. By adding +[[ref: witnesses]] that monitor and approve each version update, a malicious +actor cannot rewrite the previous history without also compromising a sufficient +number of [[ref: witnesses]]. + +An overview of the [[ref: witness]] mechanism is as follows: + +- The [[ref: DID Controller]] specifies (in the `parameters` of a [[ref: log + entry]]) a list of [[ref: witnesses]], DIDs that together with the [[ref: DID + Controller]] will contribute to "approving" all subsequent versions of the + DID. + - Ideally, the [[ref: DID Controller]] does that in the inception event for the + DID. + - Over time, the list of [[ref: witnesses]] may evolve, with each change being + approved by the declared list of [[ref: witnesses]] from before such a + change. +- The [[ref: DID Controller]] prepares a [[ref: DID Log Entry]] and shares it with + the [[ref: witnesses]]. + - The specification leaves to implementers *how* the [[ref: log entry]] data is provided to the [[ref: witnesses]]. +- Each [[ref: witness]] verifies the [[ref: DID Log Entry]], as defined by this + specification. If not, the [[ref: witnesses]] **MUST NOT** approve the [[ref: log entry]]. + - The [[ref: witnesses]] ***MUST** have their own copy of the current [[ref: + DID Log]]. +- Each [[ref: witness]] determines (based on the governance of the ecosystem) + if they approve of the DID version update. + - This specification has no opinion on what "approve" means for any + deployment of `did:tdw`. That is up to the ecosystem in which the [[ref: DID + Controller]] and [[ref: witnesses]] are participating. +- If the verification is successful and the approval granted, the [[ref: + witness]] sends a [[ref: Data Integrity]] proof to the [[ref: DID Controller]] similar + to that generated by the [[ref: DID Controller]], with the [[ref: DIDDoc]] as the signed object, + the entry log's `versionId` as the challenge, but signed by the [[ref: witnesses]] key. +- When a weighted threshold of proofs are received, the DID Controller + inserts the [[ref: witnesses]]'s proofs into the array of proofs that are the last item in + the [[ref: DID Log Entry]] and publishes the updated version of the [[ref: DID + Log]]. + - In publishing a new version of the [[ref: DID Log]], the [[ref: DID + Controller]] **SHOULD** remove the [[ref: witness]] [[ref: Data Integrity]] proofs from + earlier [[ref: entries]] to reduce the size of the log. Only the set of approval + proofs on the last [[ref: log entry]] are needed because of the chaining of the + proofs via the use of the `entryHash` challenge. + - Removing the prior entry [[ref: witness]] proofs does not affect the verifiability of + the DID because the `entryHash` calculation does not include the proofs item. + - The specification leaves to implementers how the proofs are conveyed to + the [[ref: DID Controller]]. + +::: to do + +To Do: Update to use a [[ref: Data Integrity]] Proof Set, where the authorized key identifies +the proof, and the [[ref: witnesses]] proofs reference the identifier. + +::: + +As with the handling of the `updateKeys`, [[ref: DID Log Entry]] changes require +proofs from the the [[ref: witnesses]] active *prior* to the publication of a +new version. If a new version changes the list of [[ref: witnesses]], that +change must be approved by the *prior* [[ref: witnesses]]. For the first entry +in the [[ref: DID Log]], the [[ref: witnesses]] listed in that entry must +approve the version, since there are no "prior" [[ref: witnesses]]. + +The data object for the `witness` [[ref: parameters]] item is as follows. +The threshold design borrows from the [[ref: verifiable conditions]] +specification. + +```json +"witness" : { + "threshold": n, + "selfWeight": n, + "witnesses" : [ + { + "id": "", + "weight": n + } + ] +} +``` + +where: + +- `threshold`: an integer that must be attained or surpassed by the sum of the [[ref: witnesses]] and + [[ref: DID Controller]]'s weights for a [[ref: DID log entry]] to be considered approved. +- `selfWeight`: an integer that is the weight given the [[ref: DID Controller]]'s + verified proof, in determining if the threshold has been surpassed. +- `witnesses`: an array of witnesses + - `id`: the DID of the witness + - `weight`: the weight of this [[ref: witness]]'s approval + +The use of the threshold and weighted approvals (versus needing approvals from +all [[ref: witnesses]]) is to prevent faulty [[ref: witnesses]] from blocking the publishing of +a new version of the DID. To determine if the threshold has been passed, sum the +`weight` integer of the received approvals, plus the `selfWeight` of the [[ref: DID +Controller]], and if it equal to or more than `threshold`, the update can be +published. The calculation **MUST** also be executed by resolvers processing a +DID Log. For example, if there are three [[ref: witnesses]], each with a `weight` of 1, +the [[ref: DID Controller]] with a `selfWeight` of 2, and a `threshold` of 4, the +threshold will be met by two [[ref: witnesses]] approving the change, plus the [[ref: DID +Controller]]. + +See the Implementer's Guide section on [Witnesses](#witnesses) for more +discussion on the witness capability and using it in production scenarios. + +#### Publishing a Parallel `did:web` DID + +Each time a `did:tdw` version is created, the [[ref: DID Controller]] **MAY** +generate a corresponding `did:web` to publish along with the `did:tdw`. To do +so, the [[ref: DID Controller]] **MUST**: + +1. Start with the resolved version of the [[ref: DIDDoc]] from `did:tdw`. +2. Execute a text replacement across the [[ref: DIDDoc]] of `did:tdw::` to + `did:web:`, where `` is the actual `did:tdw` [[ref: SCID]]. +3. Add to the [[ref: DIDDoc]] `alsoKnownAs` array, the full `did:tdw` DID. If the + `alsoKnownAs` array does not exist in the [[ref: DIDDoc]], it **MUST** be added. +4. Publish the resulting [[ref: DIDDoc]] as the file `did.json` at the web location + determined by the specified `did:web` DID-to-HTTPS transformation. + +The benefit of doing this is that resolvers that have not been updated to +support `did:tdw` can continue to resolve the [[ref: DID Controller]]'s DIDs. +`did:web` resolvers that are aware of `did:tdw` features can use that knowledge, +and the existence of the `alsoKnownAs` `did:tdw` data in the [[ref: DIDDoc]] to get the +verifiable history of the DID. + +The risk of publishing the `did:web` in parallel with the `did:tdw` is that the +added security and convenience of using `did:tdw` are lost. + +### DID URL Resolution + +The `did:tdw` DID Method embraces the power and usefulness of DID URLs, along +with the semantic simplicity of using them with a web-based DID method. +Specifically, a `did:tdw` implementation **MUST**: + +- Resolve the `/whois` DID URL path using a [[spec:LINKED-VP]] service, whether + or not it exists in the `did:tdw` [[ref: DIDDoc]], returning a [[ref: Verifiable + Presentation]], if published by the [[ref: DID Controller]], found at the same + path as the `did.jsonl` file, using the `/whois.vp` filename component, and + the `application/vp' media type, as per the [IANA Verifiable Presentation + Assignment](https://www.iana.org/assignments/media-types/application/vp). + - For example, `did:tdw:{SCID}.example.com/whois` returns the [[ref: verifiable + presentation]] from `https://{SCID}.example.com/.well-known/whois.vp`. +- Resolve any `did:tdw` DID URL using a [[spec:DID-CORE]] `relativeRef` DID + [[ref: parameter]], whether or not a supporting service exists in the `did:tdw` [[ref: DIDDoc]], + returning the file found at web location corresponding to the DID-to-HTTPS + transformation. + - For example, resolving `did:tdw:example.com:{SCID}/governance/issuers.json` returns + the file `https://example.com/{SCID}/governance/issuer.json` + - When the `{SCID}` is placed as a subdomain, the file is found relative to + that subdomain, and not in the `.well-known` folder where the `did.jsonl` + file is found. For example, resolving + `did:tdw:{SCID}.example.com/governance/issuers.json` returns the file + `https://{SCID}.example.com/governance/issuer.json`. + +In both cases, a [[ref: DID Controller]] **MAY** define services in the DIDDoc +that override the default services that **MUST** be resolved by the `did:tdw` +DID Method. + +The sections below formalize the services that exist by default in `did:tdw` and +how a [[ref: DID Controller]] can override them. + +#### whois LinkedVP Service + +The `#whois` service enables those that receive a `did:tdw` DID to retrieve and +a [[ref: Verifiable Presentation]] (and embedded [[ref: Verifiable +Credentials]]) the [[ref: DID Controller]] has decided to publish about itself. +The intention is that anyone wanting to learn more about a particular `did:tdw` +DID can resolve the `/whois` DID URL to retrieve a [[ref: Verifiable +Presentation]] published by the [[ref: DID Controller]] that contains [[ref: +Verifiable Credentials]] with the DID as the subject. The DID Controller +includes in the [[ref: Verifiable Presentation]] any [[ref: Verifiable Credentials]] that it +thinks might be helpful for resolvers in making a trust decision about the [[ref: DID +Controller]]. + +It is up to the [[ref: DID Controller]] to decide to publish a `whois` +[[ref: verifiable presentation]], and which [[ref: verifiable credentials]] to put into the +[[ref: verifiable presentation]]. It is up to a DID resolver to decide what attestations +from third parties are useful in making a trust decision about the [[ref: DID +Controller]]. + +`did:tdw` DIDs **automatically** supports a `/whois` service endpoint with the +following definition based on the [[spec:LINKED-VP]] specification, with the +`serviceEndpoint` defining a similar `did:tdw` DID-to-HTTPS DID Log +transformation with `did.jsonl` changed to `whois.vp`. Differing from the +[DID-to-HTTPS transformation](#the-did-to-https-transformation) is that the +`.well-known/` component of the `did.jsonl` transformation is dropped from the +`whois.vp` resolution. + +```json +{ + "@context": "https://identity.foundation/linked-vp/contexts/v1", + "id": "#whois", + "type": "LinkedVerifiablePresentation", + "serviceEndpoint": "/whois.vp" +} +``` + +The returned `whois.vp` **MUST** contain a [[ref: W3C VCDM]] [[ref: verifiable +presentation]] signed by the DID and containing [[ref: verifiable credentials]] +that **MUST** have the DID as the `credentialSubject`. + +A [[ref: DID Controller]] **MAY** explicitly add to their [[ref: DIDDoc]] a `did:tdw` +service with the `"id": "#whois"`. Such an entry **MUST** override the implicit +`service` above. If the [[ref: DID Controller]] wants to publish the `whois` +[[ref: verifiable presentation]] in a different format than the [[ref: W3C +VCDM]] format, they **MUST** explicitly add to their [[ref: DIDDoc]] a service with the +`"id": "#whois"` to specify the name and implied format of the [[ref: verifiable +presentation]]. + +To resolve the DID URL `/whois`, the resolver **MUST**: + +1. Resolve the given `did:tdw` DID by retrieving, processing, and verifying the + [[ref: DID log]] for the `did:tdw` as defined in this specification. +2. Find the [[ref: DIDDoc]] `service` with the `id` `#whois`, if any, or use the implicit + service (above). +3. Resolve the `serviceEndpoint` URL, if possible, and return the document + found. + 1. If the `serviceEndpoint` URL can't be resolved by the resolver (such as if + the URL protocol is not supported by the resolver), the error `Error XXX: + YYY` **MUST** be returned. + 2. If the file at the defined `serviceEndpoint` is not found, `Error + 404: Not Found` **MUST** be returned. + +#### DID URL Path Resolution Service + +The automatic resolution of `did:tdw` DID URL paths follows the +[[spec:DID-CORE]] `relativeRef` specification, as follows: + +- a DID path, such as example 2 in [section 3.2 DID URL + Syntax](https://www.w3.org/TR/did-core/#example-2) gives the example: + `did:example:123456/resume.pdf` +- In turn, that can be treated as the following, as shown in example 8 in the + same section: `did:example:123456?service=files&relativeRef=/resume.pdf` +- The `#files` service defined below then defines the `serviceEndpoint` for the + `relativeRef`. + - For `did:tdw`, that service is implicitly defined, with the + `serviceEndpoint` matching the `did:tdw` [DID-to-HTTPS + transformation](#the-did-to-https-transformation) and `did.jsonl` replaced + by the DID URL Path. If `.well-known/` is part of the HTTPS URL, it is + removed from the URL before resolving the URL. + +Thus, the implicit service for DID `did:tdw:example.com:dids:` is: + +```json +{ + "id": "#files", + "type": "relativeRef", + "serviceEndpoint": "https://example.com/dids/" +} +``` + +A [[ref: DID Controller]] **MAY** explicitly add to their [[ref: DIDDoc]] a service with +the `"id": "#files"`. Such an entry **MUST** override the implicit `service` +defined above. + +To resolve the DID URL `/path/to/file`, the resolver **MUST**: + +1. Resolve the given `did:tdw` DID by retrieving, processing, and verifying the + [[ref: DID log]] for the `did:tdw` as defined in this specification. +2. Find the [[ref: DIDDoc]] `service` with the `id` `#files`, if any, or use the implicit + service (above). +3. Resolve the `serviceEndpoint` URL with the DID URL Path appended, if + possible, and return the document found at that location. + 1. If the `serviceEndpoint` URL can't be resolved by the resolver (such as if + the URL protocol is not supported by the resolver), the error `Error XXX: + YYY` **MUST** be returned. + 2. If the file at the path appended to the defined `serviceEndpoint` is not + found, the error `Error 404: Not Found` **MUST** be returned. diff --git a/spec/version.md b/spec/version.md new file mode 100644 index 0000000..b9735a3 --- /dev/null +++ b/spec/version.md @@ -0,0 +1,22 @@ +## `did:tdw` Version Changelog + +The following lists the substantive changes in each version of the specification. + +- Version 0.3 + - Removes the `cryptosuite` [[ref: parameter]], moving it to implied based on the `method` [[ref: parameter]]. + - Change base32 encoding with [[ref: base58btc]], as it offers a better expansion rate. + - Remove the step to extract part of the [[ref: base58btc]] result during the generation of the [[ref: SCID]]. + - Use [[ref: multihash]] in the [[ref: SCID]] to differentiate the different hash function outputs. +- Version 0.2 + - Changes the location of the [[ref: SCID]] in the DID to always be the first + component after the DID Method prefix -- `did:tdw::...`. + - Adds the [[ref: parameter]] `portable` to enable the capability to move a + `did:tdw` during the creation of the DID. + - Removes the first two [[ref: Log Entry]] items `entryHash` and `versionId` + and replacing them with the new `versionId` as the first item in each [[ref: log + entry]]. The new versionId takes the form `-`, + where `` is the incrementing integer of version of the + entry: 1, 2, 3, etc. + - The `/whois` media type is changed to `application/vp` and the file is + changed to `whois.vp` to match the IANA registration of a [[ref: Verifiable + Presentation]]. diff --git a/specs.json b/specs.json new file mode 100644 index 0000000..52ca64f --- /dev/null +++ b/specs.json @@ -0,0 +1,35 @@ +{ + "specs": [ + { + "title": "Trust DID Web - The did:tdw DID Method", + "spec_directory": "./spec", + "markdown_paths": [ + "header.md", + "abstract.md", + "definitions.md", + "overview.md", + "specification.md", + "security_and_privacy.md", + "implementors_guide.md", + "example.md", + "references.md", + "version.md" + ], + "source": { + "host": "github", + "account": "decentralized-identity", + "repo": "trustdidweb" + }, + "output_path": "./", + "logo": "tdw.jpg", + "logo_link": "https://github.com/decentralized-identity/trustdidweb", + "katex": true, + "external_specs": [ + { + "LINKED-VP": "https://identity.foundation/linked-vp/", + "TOIP": "https://trustoverip.github.io/ctwg-main-glossary/" + } + ] + } + ] +} \ No newline at end of file diff --git a/tdw.jpg b/tdw.jpg new file mode 100644 index 0000000..09a361e Binary files /dev/null and b/tdw.jpg differ