From 2d38d956c9f44dc86835395d016822c5aa15f9cf Mon Sep 17 00:00:00 2001
From: LiranCohen
Date: Wed, 6 Mar 2024 17:41:18 +0000
Subject: [PATCH] deploy: f0761c05574c44c8566175cf3e58da463f3754bd
---
.gitignore | 5 +
.nojekyll | 0
.vscode/settings.json | 3 +
LICENSE | 201 +
README.md | 15 +
docs/README.md | 1 +
docs/_config.yml | 17 +
docs/agenda.md | 741 +
docs/companion_guide.md | 683 +
docs/index.md | 3 +
guide/v0.0.1/index.html | 1102 ++
index.html | 1591 +++
package-lock.json | 11370 ++++++++++++++++
package.json | 11 +
.../base-authorization-payload.json | 17 +
.../records-write-authorization-payload.json | 27 +
schemas/json-schemas/definitions.json | 23 +
schemas/json-schemas/events/events-get.json | 44 +
schemas/json-schemas/general-jws.json | 26 +
schemas/json-schemas/hooks/hooks-write.json | 56 +
.../interface-methods/messages-get.json | 48 +
.../permissions-definitions.json | 41 +
.../interface-methods/permissions-grant.json | 74 +
.../permissions-request.json | 66 +
.../interface-methods/permissions-revoke.json | 45 +
.../protocol-definition.json | 49 +
.../interface-methods/protocol-rule-set.json | 71 +
.../protocols-configure.json | 45 +
.../interface-methods/protocols-query.json | 53 +
.../interface-methods/records-delete.json | 45 +
.../interface-methods/records-query.json | 94 +
.../interface-methods/records-read.json | 44 +
.../interface-methods/records-write.json | 269 +
.../interface-methods/snapshots-create.json | 45 +
.../json-schemas/jwk-verification-method.json | 26 +
schemas/json-schemas/jwk/general-jwk.json | 123 +
schemas/json-schemas/jwk/public-jwk.json | 51 +
.../json-schemas/messages/messages-get.json | 44 +
.../json-schemas/permissions/definitions.json | 57 +
.../permissions/permissions-grant.json | 69 +
.../permissions/permissions-request.json | 59 +
schemas/json-schemas/protocol-definition.json | 44 +
schemas/json-schemas/protocol-rule-set.json | 71 +
.../protocols/protocols-configure.json | 45 +
.../protocols/protocols-query.json | 54 +
.../json-schemas/records/records-delete.json | 45 +
.../json-schemas/records/records-query.json | 95 +
.../json-schemas/records/records-read.json | 44 +
.../json-schemas/records/records-write.json | 260 +
spec/0.0.1-predraft/images/topology.svg | 3 +
spec/0.0.1-predraft/index.html | 1591 +++
spec/0.0.1-predraft/spec.md | 1256 ++
spec/images/topology.svg | 594 +
spec/index.html | 1591 +++
spec/spec.md | 1416 ++
specs.json | 56 +
56 files changed, 24519 insertions(+)
create mode 100644 .gitignore
create mode 100644 .nojekyll
create mode 100644 .vscode/settings.json
create mode 100644 LICENSE
create mode 100644 README.md
create mode 100644 docs/README.md
create mode 100644 docs/_config.yml
create mode 100644 docs/agenda.md
create mode 100644 docs/companion_guide.md
create mode 100644 docs/index.md
create mode 100644 guide/v0.0.1/index.html
create mode 100644 index.html
create mode 100644 package-lock.json
create mode 100644 package.json
create mode 100644 schemas/json-schemas/authorization-payloads/base-authorization-payload.json
create mode 100644 schemas/json-schemas/authorization-payloads/records-write-authorization-payload.json
create mode 100644 schemas/json-schemas/definitions.json
create mode 100644 schemas/json-schemas/events/events-get.json
create mode 100644 schemas/json-schemas/general-jws.json
create mode 100644 schemas/json-schemas/hooks/hooks-write.json
create mode 100644 schemas/json-schemas/interface-methods/messages-get.json
create mode 100644 schemas/json-schemas/interface-methods/permissions-definitions.json
create mode 100644 schemas/json-schemas/interface-methods/permissions-grant.json
create mode 100644 schemas/json-schemas/interface-methods/permissions-request.json
create mode 100644 schemas/json-schemas/interface-methods/permissions-revoke.json
create mode 100644 schemas/json-schemas/interface-methods/protocol-definition.json
create mode 100644 schemas/json-schemas/interface-methods/protocol-rule-set.json
create mode 100644 schemas/json-schemas/interface-methods/protocols-configure.json
create mode 100644 schemas/json-schemas/interface-methods/protocols-query.json
create mode 100644 schemas/json-schemas/interface-methods/records-delete.json
create mode 100644 schemas/json-schemas/interface-methods/records-query.json
create mode 100644 schemas/json-schemas/interface-methods/records-read.json
create mode 100644 schemas/json-schemas/interface-methods/records-write.json
create mode 100644 schemas/json-schemas/interface-methods/snapshots-create.json
create mode 100644 schemas/json-schemas/jwk-verification-method.json
create mode 100644 schemas/json-schemas/jwk/general-jwk.json
create mode 100644 schemas/json-schemas/jwk/public-jwk.json
create mode 100644 schemas/json-schemas/messages/messages-get.json
create mode 100644 schemas/json-schemas/permissions/definitions.json
create mode 100644 schemas/json-schemas/permissions/permissions-grant.json
create mode 100644 schemas/json-schemas/permissions/permissions-request.json
create mode 100644 schemas/json-schemas/protocol-definition.json
create mode 100644 schemas/json-schemas/protocol-rule-set.json
create mode 100644 schemas/json-schemas/protocols/protocols-configure.json
create mode 100644 schemas/json-schemas/protocols/protocols-query.json
create mode 100644 schemas/json-schemas/records/records-delete.json
create mode 100644 schemas/json-schemas/records/records-query.json
create mode 100644 schemas/json-schemas/records/records-read.json
create mode 100644 schemas/json-schemas/records/records-write.json
create mode 100644 spec/0.0.1-predraft/images/topology.svg
create mode 100644 spec/0.0.1-predraft/index.html
create mode 100644 spec/0.0.1-predraft/spec.md
create mode 100644 spec/images/topology.svg
create mode 100644 spec/index.html
create mode 100644 spec/spec.md
create mode 100644 specs.json
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0243965
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.cache
+node_modules
+*/**/node_modules
+packages/implementation/db_??*
+packages/implementation/did-ion??*
\ No newline at end of file
diff --git a/.nojekyll b/.nojekyll
new file mode 100644
index 0000000..e69de29
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..cbb7b3a
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "liveServer.settings.port": 5502
+}
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..89f4768
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+# Decentralized Web Node
+
+### Specification
+
+Latest Draft: https://identity.foundation/decentralized-web-node/spec/
+
+### Companion Guide
+
+Latest Draft: [https://identity.foundation/decentralized-web-node/guide/](https://identity.foundation/decentralized-web-node/guide/v0.0.1/)
+
+### Implementations
+
+| Implementer | Language | Repo | Environments |
+| ----- | ----- | ------ | ----- |
+| TBD | TypeScript | [TBD54566975/dwn-sdk-js](https://github.com/TBD54566975/dwn-sdk-js) | Server, Web |
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..64b0b75
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1 @@
+This directory is used to serve github pages.
diff --git a/docs/_config.yml b/docs/_config.yml
new file mode 100644
index 0000000..ec1c41c
--- /dev/null
+++ b/docs/_config.yml
@@ -0,0 +1,17 @@
+title: Identity Hub
+description: GitHub Documentation
+url: "https://identity.foundation/identity-hub"
+
+github:
+ private: false
+ license:
+ name: Apache-2.0
+ source:
+ branch: "main"
+ path: "/docs"
+ repository_url: "https://github.com/decentralized-identity/identity-hub"
+
+plugins:
+ - jekyll-feed
+ - jekyll-seo-tag
+ - jekyll-sitemap
diff --git a/docs/agenda.md b/docs/agenda.md
new file mode 100644
index 0000000..0a5741d
--- /dev/null
+++ b/docs/agenda.md
@@ -0,0 +1,741 @@
+# DWN Bi-Weekly Calls Notes
+
+## Summary
+
+Bi-weekly DIF call notes on DWN specifications.
+
+- [Github](https://github.com/decentralized-identity/decentralized-web-node)
+- [Wiki](https://identity.foundation/decentralized-web-node/spec/)
+
+**Editors**
+
+- Dan Buchner @csuwildcat
+- Tobias Looker (Mattr)
+
+**Contributors**
+
+- Henry Tsai (Microsoft)
+- XinAn Xu (Microsoft)
+- Moe Jangda (Block)
+
+**Co-Chairs**
+
+- Andor Kesselman @andorsk email: andor@benri.io
+- Liran Cohen @lirancohen
+
+
+## DIF Meeting January 24, 2023
+
+- [Recording]()
+- Andor Kesselman
+- Alan Karp
+- Liran Cohen
+
+| Item | Segment | Time | Owner | Description |
+|-----------------------|-------------------------|--------|----------|----------------------------------------------|
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk | |
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | |
+| Slack Updates | Discussion Alignment | 10 min | @andorsk | |
+| Tags to Records | Discussion Alignment | 10 min | @liran | |
+| Issue Alignment | Issue Alignment | 10 min | @liran | |
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+### Notes:
+
+- Discussion:
+
+### Action Items
+
+- Roadmap:
+ - Status:
+ - TODO: Spec alignment.
+ - Subscription: PR
+ - Merged event subscribed. Event subscribe coming.
+ - Meet interop for MVP on spec. Not on sdk.
+ - Test Suite :
+ - Compliance test suites.
+ - Conformance Tests
+ - Finding a good balance in general
+ - dwn-sdk will have interfaces
+ - Test Vectors
+ - Avoid feature bloat. Document that specifies a minimum conformant system.
+ - Transport
+ - Needs to address.
+ - Roadmap:
+ - How do we get more engagement with the spec work?
+ - Less opinions on how it should work.
+ - Deadlines:
+ - Hard to contribute to the spec when it's not aligned.
+ - spec alignment blocking.
+ - MVP walkthrough.
+ - commit needs to go
+ - sync updated
+ - feature detection
+ - transport documentation.
+ - Alan:
+ - is interoperating important?
+ - more stuff needs to be in the spec than if that was not the case
+ - Subscription:
+ - Drop connection and then it won't renew and then reconnect drops it.
+ - If someone creates a bunch of subscriptions that won't emit messages. DDOS.
+ - Wrap up MVP spec.
+
+### Decisions
+
+- Move dwn-sdk-js notifications to a separate channel. (reach out to Dan before implementing )
+
+## DIF Meeting November 15, 2023
+
+- [Recording]()
+- Andor Kesselman
+- Alan Karp
+- Liran Cohen
+- Drummond Reed
+
+| Item | Segment | Time | Owner | Description |
+|-----------------------|-------------------------|--------|----------|----------------------------------------------|
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk | IIW Updates: |
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | |
+| Slack Updates | Discussion Alignment | 10 min | @andorsk | |
+| Tags to Records | Discussion Alignment | 10 min | @liran | |
+| Issue Alignment | Issue Alignment | 10 min | @liran | |
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+### Notes:
+
+- Discussion:
+ - Slack updates flooding discussions.
+ - Liran:
+ - Have it somewhere, but different place.
+ - Move to separate channel.
+ - Office hours on discord.
+ - Add tags to records.
+ - Index something by protocol path.
+ - Full search of data is not really obtainable in a way in which we want.
+ - @Alan: likes it
+ - Tags:
+ - What problem are they solving?
+ - Use Case: Chat Application. Within app, within the data, you have a hashtag. Data portion.
+ - Client: can tag hashtags
+ - Go get met all the hashtags.
+ - Andor: why not record as protocol?
+ - How does it fit into protocols?
+ - andor:
+ - Protocols: further consideration. defined there?
+ - Basic datastore.
+ - Liran: Tweets:
+ - You have a tweet under a protocol path. Allowed tweets.
+ - A hashtag per. Record for each hashtag. Tweets. RecordsID. Message.
+ - symbolic link in protocol. Some of that with protocol paths.
+ - A have a #awesome life
+ - Use case #1: #awesome <- all other tagged #awesome.
+ -> bucket of #awesome
+ /records/tags/#awesome
+ /record/tags/
+ - Use case #2: Search for tag #awesome.
+ - search metadata
+ - andor:
+ - question: what is the right pattern to enable the use case and preserve as much of the privacy/security/interoperability intent of a PDS (DWN)?
+ - tags: include into the DWN.
+ - Lazy search indexing.
+ - Alan : Search is not relevant to Tags:
+ - Liran: tags: ability to index data.
+ - Help queries
+ - Search different
+ - Useful
+ - Like to think about downsides more.
+ - NOSTR similar
+
+### Action Items
+- @andorsk to finish addressing https://github.com/decentralized-identity/decentralized-web-node/pull/257
+- Stawman for tags or a position.
+
+### Decisions
+
+- Move dwn-sdk-js notifications to a separate channel. (reach out to Dan before implementing )
+
+## DIF Meeting November 1, 2023
+
+- [Recording]()
+- Andor Kesselman
+- Alan Karp
+- Liarn
+- Dan
+
+
+| Item | Segment | Time | Owner | Description |
+|-----------------------|-------------------------|--------|----------|----------------------------------------------|
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk | IIW Updates: |
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | |
+| Issue Alignment | Issue Alignment | 10 min | @liran | |
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+### Notes:
+
+- Discussion:
+ - Alan Karp:
+ - Confused Deputy problem.
+ - Dan: Implicit
+ - Alan: Security risk
+ - Example:
+ - Alan: Only had read permission to Foo
+ - Dan: RW permission to foo
+ - Vulnerability:
+ - Alan: You may want to say
+ - Alan: when you do an invocation, use a capability
+ - Can prove valid capability by evidence.
+ - Dan: Always first fetch object that was there.
+ - Cannot just interact with a protocol.
+ - Alan:
+ - Role cert: Delegate a specific permission to myself
+ - Alan: 10 objects to a collection
+ - Delegate to myself
+ - Dan: What is that look like?
+ - Anyone?
+ - What is invocation of capability:
+ - Assign role certificate
+ - Block everyone inband
+ - Role held by verifier.
+ - Wrap around capability for object foo.
+ - Without having certificate yourself, by proving your role.
+ - Dan: what are the bytes.
+ - Signing something that proves control of the did
+ - Proof of delegation is valid.
+ - Verifier: look at role and possible permissions
+ - Alan: Vulenerability: on lookup
+ - Invocation Today:
+ - Prove some role
+ - Separate cert: which object and permission
+ - Andor: How to move forward?
+ - Normative change: Verification changes
+ - Role is proof of delegation
+ - Capability creates a role.
+ - When evaluating capabilities, force invoker but with specific action
+ - Good explanation: https://w3c-ccg.github.io/zcap-spec/
+ - Delegate to a program on behalf.
+
+- Action Item:
+ - [ ] Discuss on whether to add extra step to capabilities not roles.
+
+## DIF Meeting October 18, 2023
+
+- [Recording]()
+- Andor Kesselman
+- Alan Karp
+
+Meeting agenda today is light. TBD team may not be available today and there has been no work happening since last two weeks.
+
+Request for more contributions.
+
+| Item | Segment | Time | Owner | Description |
+|-----------------------|-------------------------|--------|----------|----------------------------------------------|
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk | IIW Updates: |
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | |
+| Issue Alignment | Issue Alignment | 10 min | @liran | |
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+### Notes:
+
+Alan at IIW:
+- Lots of conversation about authorization
+- OPA
+- Different UI's for expressing policy
+
+Action Item: Add a few issues related to high priority changes.
+
+## DIF Meeting October 4, 2023
+
+- [Recording]()
+- Andor Kesselman
+- Liran Cohen
+- Ajay Jadhav
+
+
+| Item | Segment | Time | Owner | Description |
+|-----------------------|-------------------------|--------|----------|----------------------------------------------|
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk | |
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | |
+| Issue Alignment | Issue Alignment | 10 min | @liran | |
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+Action Item: Add a few issues related to high priority changes.
+
+## DIF Meeting September 30, 2023
+
+- [Recording]()
+- Andor Kesselman
+- Liran Cohen
+- Alan Karp
+- Henry Tsai
+-
+
+| Item | Segment | Time | Owner | Description |
+|-----------------------|-------------------------|--------|----------|----------------------------------------------|
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk | |
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | |
+| Issue Alignment | Issue Alignment | 10 min | @liran | |
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+## DIF Meeting September 16, 2023
+
+- [Recording]()
+- Andor Kesselman
+- Liran Cohen
+- Alan Karp
+
+| Item | Segment | Time | Owner | Description |
+| ----------------------------------------- | ----------------------- | ------ | --------------- | ------------------------------------------------------------------------------- |
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk ||
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | |
+| Issue Alignment | Issue Alignment | 10 min | @liran | |
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+## DIF Meeting Aug 23, 2023
+
+
+- [Recording]()
+- Andor Kesselman
+- Liran Cohen
+- Alan Karp
+
+| Item | Segment | Time | Owner | Description |
+| ----------------------------------------- | ----------------------- | ------ | --------------- | ------------------------------------------------------------------------------- |
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk ||
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | |
+| Issue Alignment | Issue Alignment | 10 min | @liran | |
+| Calls To Action | Closing | 5 min | @andorsk | |
+### Issues Diccussed:
+
+
+
+## DIF Meeting Aug 9, 2023
+
+- [Recording]()
+- Andor Kesselman
+- Liran Cohen
+- Dan Buchner
+- Alan Karp
+
+| Item | Segment | Time | Owner | Description |
+| ----------------------------------------- | ----------------------- | ------ | --------------- | ------------------------------------------------------------------------------- |
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk ||
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | |
+| Issue Alignment | Issue Alignment | 10 min | @liran | |
+| Calls To Action | Closing | 5 min | @andorsk | |
+### Issues Diccussed:
+
+
+
+
+## DIF Meeting July 26, 2023
+
+[Recording](https://us02web.zoom.us/rec/share/Ru-733Ay07GGp4ezra82DFgj8Z9lOP_5Esv5yC6JWUBABxnLL954lHU0GgQMsgk.UypvAnC55W7ai0ML)
+
+- Andor Kesselman
+- Liran Cohen
+- Moises Jaramillo
+- Alan Karp
+- Dan Bucher
+
+| Item | Segment | Time | Owner | Description |
+| ----------------------------------------- | ----------------------- | ------ | --------------- | ------------------------------------------------------------------------------- |
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk ||
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | Review PR 250, 252, and 253 |
+| Issue Alignment | Issue Alignment | 10 min | @liran | |
+| Calls To Action | Closing | 5 min | @andorsk | |
+### Issues Diccussed:
+
+
+## DIF Meeting July 12, 2023
+
+* [Recording](https://us02web.zoom.us/rec/share/abvaO-V7lvTT0NZhcb6PFdQKVbc3O41S4GfgxkLDz92SkDFccvhB2qDElGA5SdfJ.wpr79nv0ANt2j-d4)
+
+- Ian Preston
+- Dan Buchner
+- Andor Kesselman
+- Alan Karp
+- Liran Cohen
+
+
+| Item | Segment | Time | Owner | Description |
+| ----------------------------------------- | ----------------------- | ------ | --------------- | ------------------------------------------------------------------------------- |
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk ||
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | |
+| [Peergos Discussion]() | Updates | 10 min | @ian | |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | Alignment |
+| Issue Alignment | Issue Alignment | 10 min | @liran | Alignment |
+| Calls To Action | Closing | 5 min | @andorsk | |
+### Issues Diccussed:
+
+### Notes:
+
+- Peergos Discussion:
+ - 2013:
+ - Before IPFS
+ - Identity/Fine Grained Access Control/Encryption
+ - Global Access Control File System
+ - Grant: Read|Write access to individual files or folders
+ - Conventional login (username + password). Key derivation is from there.
+ - Hide metadata
+ - Server can't tell if blob is directory of file
+ - Technical Difficult:
+ - Don't want to depend on DNS
+ - 2018: Decided HTTP over P2P Streams
+ - Peergos Implementation:
+ - Peergos
+ - Question: Alan
+ - Correlation Inference?
+ - Don't consider server based timing attacks are not in scope.
+ - Liran: Identity Portion:
+ - Node identity
+ - User identity <- least happy with PKI global append only log signed statements of username. Add people by username over UX. Considering removing PKI entirely.
+ - Question: Capability based.
+ - Everthing split into writing subspaces.
+ - KP Control
+ - W/e Changes you write are atomic.
+ - Sandbox application.
+ - Not sure if it makes sense in Peergos
+ - Dan:
+ - How can apps expose public information in public way? Champs. Maps to encrypted blobs.Keep capability of Champ in sync with real data. Look up and do traversal. Web interface. Can publish a website. Can view in any gateway.
+ - Henry:
+ - Were there challenges around encryption, e.g.
+ 1. Sharing keys to friends/external participants
+ 2. Key rolling
+ - Cryptree
+ - Voila <- 2008
+ - Care alot about being post quantum.
+ - Grant a read capability is basically sharing a key.
+ - Expensive: Revoke write access, rotate all the keys.
+ - Sharing capabilities: each person has an inbox. Public encryption key. People write to that to share capabilities.
+ - How many?
+ - 10 Self Hosters
+
+### Issues Discussed:
+
+- [Requiring fine-grained capabilities #142
+](https://github.com/decentralized-identity/decentralized-web-node/issues/142) To revisit after Spec alignment. Milestone 1.
+- [Revocation Subtleties #138
+](https://github.com/decentralized-identity/decentralized-web-node/issues/138) - To revisit after spec alignment. Milestone 1.
+
+
+## DIF Meeting June 28, 2023
+
+* [Recording]()
+
+- Alan Karp
+- Liran Cohen
+- Andor Kesselman
+- Henry Tsai
+- Drummond Reed
+
+| Item | Segment | Time | Owner | Description |
+| ----------------------------------------- | ----------------------- | ------ | --------------- | ------------------------------------------------------------------------------- |
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk | [Update peergos description in companion_guide #231](https://github.com/decentralized-identity/decentralized-web-node/pull/231) |
+| Peergos Discussion with Ian? | Companion Guide Updates | 5 min | | |
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | |
+| Agenda | Spec PR Review | 10 min | | |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | Alignment |
+| Issue Alignment | Issue Alignment | 10 min | @liran | Alignment |
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+### Issues Discussed:
+
+- [Requiring fine-grained capabilities #142
+](https://github.com/decentralized-identity/decentralized-web-node/issues/142) To revisit after Spec alignment. Milestone 1.
+- [Revocation Subtleties #138
+](https://github.com/decentralized-identity/decentralized-web-node/issues/138) - To revisit after spec alignment. Milestone 1.
+
+## DIF Meeting June 14, 2023
+
+* [Recording](https://us02web.zoom.us/rec/share/Vjsy2TkDWy8TxBeBsXCp5ebw6tH2cFwm6OEVoKpK8tzXng6oxI0oC9MPHjm830xS.Z-fnRwAFjPBx2BP7)
+
+
+| Item | Segment | Time | Owner | Description |
+| ----------------------------------------- | ----------------------- | ------ | --------------- | ------------------------------------------------------------------------------- |
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk | [Update peergos description in companion_guide #231](https://github.com/decentralized-identity/decentralized-web-node/pull/231) |
+| Peergos Discussion | Companion Guide Updates | 10 min | | |
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | |
+| Agenda | Spec PR Review | 10 min | | |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | Alignment |
+| Issue Alignment | Issue Alignment | 10 min | @liran | Alignment |
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+### Issues Discussed:
+
+- https://github.com/decentralized-identity/decentralized-web-node/pull/228 : Dan to Look at
+- https://github.com/decentralized-identity/decentralized-web-node/issues/234 : Andor
+- https://github.com/decentralized-identity/decentralized-web-node/pull/231 : Going to see if we can get Ian to comment on this. @andorsk to draft a response.
+- https://github.com/decentralized-identity/decentralized-web-node/pull/233
+- Skipping Service Endpoint Section For Next Call
+Andor: add something about scalability in abstract
+TODO: Check status on spec
+- Section 8 and 9 will be re-written in the near future.
+- Alignment Issues: https://github.com/decentralized-identity/decentralized-web-node/issues?q=is%3Aissue+is%3Aopen+label%3A%22attr%3A+alignment-effort%22
+
+## DIF Meeting May 31, 2023
+
+* [Recording](https://us02web.zoom.us/rec/share/UYcdp_7UO1ebQ4uFc84AnasAhSmW9Laxs1s2kVRgs48PLywyV12NqoyF800nHEV7.d0hxy8WiCovW8c_j)
+
+
+| Item | Segment | Time | Owner | Description |
+| ----------------------------------------- | ----------------------- | ------ | --------------- | ------------------------------------------------------------------------------- |
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk/Moises | [added dwn and peergos to the comparison guide #229](https://github.com/decentralized-identity/decentralized-web-node/pull/229) [Local, Remote, and Relay Nodes. #225](https://github.com/decentralized-identity/decentralized-web-node/pull/225) |
+| [Ecosystem Updates]() | Updates | 10 min | @andorsk | protocols.preview.benri.io |
+| Agenda | Spec PR Review | 10 min | @csuwildcat | [update the Service Endpoint section of the spec #228](https://github.com/decentralized-identity/decentralized-web-node/pull/228) [added JSON schemas for DWN specification #209](https://github.com/decentralized-identity/decentralized-web-node/pull/209) |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | Alignment |
+| Issue Alignment | Issue Alignment | 10 min | @liran | Alignment |
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+### Issues Discussed:
+
+- [Authorization layer should limit the amount of data permitted to be stored by a application #96](https://github.com/decentralized-identity/decentralized-web-node/issues/96)
+- [Add use cases link #83](https://github.com/decentralized-identity/decentralized-web-node/issues/83)
+- [Test Suite Design #213](https://github.com/decentralized-identity/decentralized-web-node/issues/213)
+- [Revocation Subtleties #138](https://github.com/decentralized-identity/decentralized-web-node/issues/138)
+- [Requiring fine-grained capabilities #142](https://github.com/decentralized-identity/decentralized-web-node/issues/142)
+- [as a developer, I can follow docs to run the reference implmentation, so I can test it out and then contribute improvements or passing test-suites #144](https://github.com/decentralized-identity/decentralized-web-node/issues/144)
+- [Support both folder based and schema based object storage #190](https://github.com/decentralized-identity/decentralized-web-node/issues/190)
+
+## DIF Meeting May 17, 2023
+
+* [Recording](https://us02web.zoom.us/rec/share/BURjRNnQ2po6lULH-MCit-GrK-i7DIKa3z9Tdqn0TF9j3Usjj52ho2P6Ft5rxaI9.Emf4aY__Zwrbm79H)
+
+### Attendees
+
+- Andor Kesselman @andorsk
+- Liran Cohen @lirancohen
+- Alan Karp
+- Ajay Jadhav
+- Kirill mee.foundation.developer
+- Drummond Reed
+
+### Agenda
+
+| Item | Segment | Time | Owner | Description |
+| ----------------------------------------- | ----------------------- | ------ | --------------- | ------------------------------------------------------------------------------- |
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk/Moises | [added dwn and peergos to the comparison guide #229](https://github.com/decentralized-identity/decentralized-web-node/pull/229) [Local, Remote, and Relay Nodes. #225](https://github.com/decentralized-identity/decentralized-web-node/pull/225) |
+| [TBD Updates]() | Updates | 10 min | @csuwildcat | |
+| Agenda | Spec PR Review | 10 min | @csuwildcat | [update the Service Endpoint section of the spec #228](https://github.com/decentralized-identity/decentralized-web-node/pull/228) [added JSON schemas for DWN specification #209](https://github.com/decentralized-identity/decentralized-web-node/pull/209) |
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | Alignment |
+| Issue Alignment | Issue Alignment | 10 min | @liran | Alignment |
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+
+## DIF Meeting May 3, 2023
+
+* [Recording](https://us02web.zoom.us/rec/share/hGruCrcoOs9FaNuryuQlCLTFIOONSNC98-BTCqg1uypG5kD9NY0lT4CQFRlxTO34.gBW6RZlFYRb_Nbf0)
+
+### Attendees
+
+- Andor Kesselman @andorsk
+- Liran Cohen @liran
+- Dan Buchner @csuwildcat
+- @Moises Jaramillo
+- Paul Trevithick
+- Drummond Reed
+
+### Agenda
+
+| Item | Segment | Time | Owner | Description |
+| ----------------------------------------- | ----------------------- | ------ | --------------- | ------------------------------------------------------------------------------- |
+| Intro | Intro | 5 min | @liran | Quick Intro. New Members. DIF IPR agreement. |
+| Agenda | Companion Guide Updates | 10 min | @andorsk/Moises | Merge https://github.com/decentralized-identity/decentralized-web-node/pull/226 |
+| [TBD Updates]() | Updates | 10 min | @csuwildcat | encryption support sync this week. in testing. biggest outstanding thing is permissions |
+| IIW Updates and Ecosystem Chat | Discussion | 20 min | @andorsk @liran @csuwildcat |
+| Permission Discussion | Discussion | 10 min | @csuwildcat | ||
+| Spec Alignment | Spec Alignment | 10 min | @andorsk | Alignment |
+| Issue Alignment | Issue Alignment | 10 min | @liran | Alignment |
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+### Notes
+
+- Merged Companion Guide Updates - Comparison Matrix from Moises
+- Merged agenda
+- Permission Discussion:
+ - DM Opens Start
+ - What happens if you have your DM's open, you accrue some DM's and you want to turn that section off.
+ - Discussion on sync and latency
+ - Proposal: End of the week
+- Aligned: asap to align spec.
+- Flag section
+- Party at Bitcoin Conf:
+ - 18th 6PM Miami time.
+
+## DIF Meeting March 22, 2023
+
+Again this week we are overbooked with content. That's because we have a lot of cleanup to do!
+
+### Attendees
+
+- Andor Kesselman @andorsk
+- Liran Cohen
+- Dan Buchner @csuwildcat
+
+## DIF Meeting March 22, 2023
+* [Recording](https://us02web.zoom.us/rec/share/SW5VZtYayd21HDKOQcGcPJJRsSvvwzHCcrxfJXm55iK94QoZ4who5cnCdW47pYC9.vCyjDuKgDCLCXoxw)
+
+Again this week we are overbooked with content. That's because we have a lot of cleanup to do!
+
+### Attendees
+
+- Andor Kesselman @andorsk
+- Liran Cohen
+- Dan Buchner @csuwildcat
+
+### Agenda
+
+| Item | Segment | Time | Owner | Description |
+| ----- | ------- | ----- | -------- | -------------------------------------------- |
+| Intro | Intro | 5 min | @andorsk | Quick Intro. New Members. DIF IPR agreement. |
+| Spec Updates | Updates | 5 min | @liran |[Interface & Method Props](https://github.com/decentralized-identity/decentralized-web-node/commit/e964c28a3712b3873e041e614c2c5fb9c5878855) |
+| Companion Guide Updates | Updates | 5 min | @andorsk | - Tall Ted Comments on [#216](https://github.com/decentralized-identity/decentralized-web-node/pull/216) |
+| [TBD Updates]() | Updates | 10 min | @csuwildcat | - Close on the web5 sdk front. Will make working with the DWN much easier. - Dan working on encryption prototype ETA couple weeks. - Moe : Sync next week start. - https://github.com/TBD54566975/web5-js NOTE: alpha https://codesandbox.io/p/sandbox/trusting-mountain-u91fjr?file=%2Fsrc%2Findex.mjs&selection=%5B%7B%22endColumn%22%3A40%2C%22endLineNumber%22%3A121%2C%22startColumn%22%3A40%2C%22startLineNumber%22%3A121%7D%5D |
+| PR Review | Maintenence | 5 min | @andorsk | - [#217](https://github.com/decentralized-identity/decentralized-web-node/pull/217) - [#216](https://github.com/decentralized-identity/decentralized-web-node/pull/216) - [#215](https://github.com/decentralized-identity/decentralized-web-node/pull/215) |
+| Milestones and Dates | Discussions | 10 min | @andorsk | [#214](https://github.com/decentralized-identity/decentralized-web-node/issues/214)|
+| TBD Alignment Updates | Discussions | 10 min | @csuwildcat | |
+| Add Technology Comparison Matrix to Companion Guide #212 | Discussions | 10 min | @moisesja | [#212](https://github.com/decentralized-identity/decentralized-web-node/issues/212)
+| Companion Guide Security Section | Discussions | 10 min | @andorsk | [#218](https://github.com/decentralized-identity/decentralized-web-node/issues/218)
+| Label Review and Tagging | Maintenence | 20 min | @liran |Go through each open issue and figure out strategy to close them|
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+### Notes
+
+- PR Review: Suggestion by @lirancohen: Bring up in meetings and give time until next meeting to approve/merge.
+- [Potential Encryption Scheme from Block](https://codesandbox.io/p/sandbox/trusting-mountain-u91fjr?file=%2Fsrc%2Findex.mjs&selection=%5B%7B%22endColumn%22%3A15%2C%22endLineNumber%22%3A121%2C%22startColumn%22%3A15%2C%22startLineNumber%22%3A121%7D%5D)
+- Mid-April Jukebox App - Play music from DWN Nodes.Trying to bend the model of how it differs from NOSTR.
+- Dan: April 5 : Austin Texas TBD building docs. Open to meeting and getting some contributions.
+- [Milestone 1: August](https://github.com/decentralized-identity/decentralized-web-node/milestone/1)
+
+Suggestion For Next Meeting:
+
+- Get consensus for get together next meeting @ Austin.
+
+
+#### Action Items
+- [ ] Find a cryptographer to look at the encryption scheme for DWN. @lirancohen will ask around. @andorsk as well.
+- [ ] Call next week : Spec walkthrough. Henry to run through the spec and update it to the current state of the sdk.
+
+## DIF Meeting March 8, 2023
+
+* [Recording](https://us02web.zoom.us/rec/share/SzX33iVda2e-fHTA59kBo1HcxOdC_jKEpPK2AbudkJd6rSs1VyB_jcmukmgGPCI3.UXhKc_QMpnSSUqDV)
+
+### Attendees
+
+- Andor Kesselman @andorsk
+- Dan Buchner @csuwildcat
+- Kaliya
+- Clare Nelson (DIF)
+- Liran Cohen
+- Moises Jaramillo
+- Paul Trevithick
+- Reuben
+- Steve
+- Sergey Kucherenko
+- Kirill Khalitov
+
+### Agenda
+
+Note: We are over-booked today in terms of content! Currently at 105 minutes, we
+will have to figure out ways to shave or push off some of these conversations.
+
+| Item | Segment | Time | Owner | Description |
+| ------------------------------------------------------------------------------------------------------ | ----------- | ------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Co-Chair Updates. Nominate Liran as Co-Chair. | Intro | 5 min | @andorsk @liran | Kaliya to follow up |
+| Spec Updates | Updates | 5 min | @andorsk | No updates to the specs |
+| Companion Guide Updates | Updates | 10 min | @andorsk @moises | - [Questions on AMA](https://github.com/decentralized-identity/decentralized-web-node/pull/216) - [Comparision Matrix (Moises)](https://github.com/decentralized-identity/decentralized-web-node/issues/212) : List of comparables, SOLID PODS, KERI, |
+| [TBD Updates]() | Updates | 10 min | @csuwildcat | - MessageStore Refactoring - Add participants actor to Protocol rules #242 |
+| [Issue 210](https://github.com/decentralized-identity/decentralized-web-node/issues/210) | Maintenance | 5 min | @csuwildcat | |
+| [Issue 208](https://github.com/decentralized-identity/decentralized-web-node/issues/208) | Maintenance | 5 min | @csuwildcat | |
+| [Issue 207](https://github.com/decentralized-identity/decentralized-web-node/issues/207) | Maintenance | 5 min | @andorsk | |
+| Tagging and Milestones | Discussion | 10 min | @andorsk | |
+| Specification Updates Discussion | Discussion | 5 min | @andorsk | Alignment on DWN-SDK vs. spec. TODO: Code spec review. @andor to set an issue. |
+| [Milestones and Dates](https://github.com/decentralized-identity/decentralized-web-node/issues/214) | Discussion | 20 min. | @andorsk | Better clarity on milestones and dates |
+| [Schema PR](https://github.com/decentralized-identity/decentralized-web-node/pull/209) | Discussion | 10 min. | @andorsk | Schemas for objects in DWN |
+| [Test Suite Conversation](https://github.com/decentralized-identity/decentralized-web-node/issues/213) | Discussion | 10 min. | @andorsk | Questions around test suite |
+| Encryption Brainstorming | Discussion | 10 min | @csuwildcat | |
+| Calls To Action | Closing | 5 min | @andorsk | |
+
+### Notes
+
+* Expanded Query Support:
+* Making the use of DWNs easier.
+* https://github.com/TBD54566975/web5-js
+* Rollup of everything. DID Support. Not instantiation.
+* Easier to interface
+* Q: SDK up to date with the spec? A: Yes, but sync spec text to add
+@Clare: to look onto documentation on how to milestone this.
+* Encryption Discussion:
+ * Dan: Cryptree
+* Drummond: ToIP TSP interested in how all these components interlock. Question about EDV encryption.
+* Q: There is a diagram at the very top of the standard draft and it mentions that each DWN is also a relay server. Do you consider any modifications where the relay server is not self-hosted but is an external service? @andorsk to add onto the companion guide with an answer.
+Paul: To help expand on the use case section.
+- Andor Q: Protocol repository at DIF? Liran: not sure. Drummond: nomenclature issue. Protocol as a term is hard term in the larger ecosystem. Must distinguish between Protocol. Paul: Agrees. Discusses **meta-protocol**. Dan: agrees with putting in the repo. Clare: **IPR to consider**
+```mermaid
+graph TD
+MetaProtocol[Meta Protocol]
+BaseProtocol[Base Protocol]
+MetaProtocol --> BaseProtocol
+```
+
+
+## DIF Meeting February 22, 2023
+* [Recording](https://us02web.zoom.us/rec/share/IL6w4JnvQUJC_qgXYmfPphrTHs2zWmVeGAo2RjuQ4-rTH7yRLpIeAwNS3SDBklYX.1UpamO7QSnkdx-8f)
+### Attendees
+
+- Andor Kesselman @andorsk
+- Dan Buchner @csuwildcat
+- kaliya
+- Liran Cohen
+- Ajay Jadhav
+- Drummond Reed @talltree
+- Sergey Kucherenko
+- Clare Nelson
+- Paul Trevithick
+
+### Agenda
+
+| Item | Time | Owner | Description |
+| ------------------------------------ | ------ | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Co-Chair Intro and Co-Chair Call** | 5 min | @andorsk | Intro, meeting notes, and discuss [efforts to find a co-chair](https://hackmd.io/@andorsk/H16_4_w6j/edit) |
+| **Office Hours Announcement** | 5 min | @csuwildcat | Mention DWN office hours happening on the TBD discord channel |
+| **New Issues/PRs** | 15 min | @andorsk @csuwildcat | Discuss the following issues: [#208](https://github.com/decentralized-identity/decentralized-web-node/issues) [#207](https://github.com/decentralized-identity/decentralized-web-node/issues/207) |
+| **TBD Updates** | 15 min | @csuwildcat | Any updates from Dan/TBD related to new work/open repos. **SDK Updates** - DWN Aggregator Bump to [0.0.22](https://github.com/TBD54566975/dwn-sdk-js/commit/576fda4858423b6ea80209997865d7470c811525) - [#231 introduced DataStore as a peer interface to MessageStore #233](<[asdf](https://github.com/TBD54566975/dwn-sdk-js/commit/576fda4858423b6ea80209997865d7470c811525)>) **Tool Updates** - DWN Aggregator - Music App? |
+| **Open PR: Discussion #206** | 15 min | @andorsk | [#206](https://github.com/decentralized-identity/decentralized-web-node/pull/206). Discuss overview and Q&A section. |
+| **Calls to Action** | 5 min | @andorsk | Note calls to action |
+
+### Notes
+
+Question from Paul: why store in electron? Dan: can store keys 1:1 way
+
+### Calls to Action
+
+- [ ] Co-chair @kaliya posted a list
+- [ ] Note your questions in Github! Highly upvoted questions will make their way over to companion guide.
+- [ ] Alex offerred to spin up a possible video to help people get started.
+- [ ] Suggestion: Guest blog on DIF. Introduction and call to action.
+- [ ] @andorsk to merge PR 206 in.
diff --git a/docs/companion_guide.md b/docs/companion_guide.md
new file mode 100644
index 0000000..d7cf773
--- /dev/null
+++ b/docs/companion_guide.md
@@ -0,0 +1,683 @@
+# Decentralized Web Node Companion Guide
+
+========
+
+**Status:** Draft
+
+**Latest Draft:**
+ [identity.foundation/decentralized-web-node/guide](https://identity.foundation/decentralized-web-node/guide)
+
+
+**Chairs**
+- [Andor Kesselman](https://www.linkedin.com/in/andorsk/)
+- [Liran Cohen](https://www.linkedin.com/in/itsliran/)
+
+**Editors:**
+- [Daniel Buchner](https://www.linkedin.com/in/dbuchner/) (Block)
+
+**Contributors:**
+- [Moises Jaramillo](https://www.linkedin.com/in/moisesjaramillo/)
+
+**Participate:**
+- [GitHub repo](https://github.com/decentralized-identity/decentralized-web-node)
+- [File a bug](https://github.com/decentralized-identity/decentralized-web-node/issues)
+- [Commit history](https://github.com/decentralized-identity/decentralized-web-node/commits/main/docs/companion_guide.md)
+
+------------------------------------
+
+**Note: This document is a WORKING DOCUMENT and IN PROGRESS.**
+
+
+
+**Table of Contents**
+
+- [Decentralized Web Node Companion Guide
+ (DWN)](#decentralized-web-node-companion-guide-dwn)
+ - [Overview ](#overview-chatgpt)
+ - [What Are Decentralized Web Nodes?
+ ](#what-are-decentralized-web-nodes-chatgpt)
+ - [Target Audience ](#target-audience-chatgpt)
+ - [Scope ](#scope-chatgpt)
+ - [Disclaimer](#disclaimer)
+ - [Terminology ](#terminology-chatgpt)
+ - [Technology Comparision](#technology-comparision)
+ - [Architecture and Components
+ ](#architecture-and-components-chatgpt)
+ - [Node Discovery and Peer-to-Peer Networking
+ ](#node-discovery-and-peer-to-peer-networking-chatgpt)
+ - [Data Sharing and Interoperability
+ ](#data-sharing-and-interoperability-chatgpt)
+ - [Security and Privacy ](#security-and-privacy-chatgpt)
+ - [Testing and Debugging ](#testing-and-debugging-chatgpt)
+ - [Deployment and Operations ](#deployment-and-operations-chatgpt)
+ - - [Local, Remote Nodes, and Relays](#local-remote-nodes-and-relays)
+ - [Example Deployment (Simple)](#example-deployment-simple)
+ - [Example Deployment (Complex)](#example-deployment-complex)
+ - [Miscellaneous](#miscellaneous)
+ - [Example Use Cases](#example-use-cases)
+ - [Real World Applications](#real-world-applications)
+ - [DWN Adoption](#dwn-adoption)
+ - [Ecosystem interplay](#ecosystem-interplay)
+ - [Limitations and Other
+ Considerations](#limitations-and-other-considerations)
+ - [Q&A](#qa)
+ - [Reference Implementations](#reference-implementations)
+
+
+
+## Overview
+
+The Decentralized Web Node (DWN) companion guide is a non-normative guide that
+provides an overview of the functional requirements and design processes for
+implementing the DWN specification developed by the Decentralized Identity
+Foundation (DIF). This guide is intended to be used by developers, architects,
+and solution providers who are interested in building decentralized web
+applications and services that conform to the DWN specification.
+
+This companion guide is not a [formal
+specification](https://identity.foundation/decentralized-web-node/spec/), but
+rather a practical resource that provides guidance on implementing the DWN
+specification in a way that promotes best practices and ensures interoperability
+with other decentralized web nodes. The guide covers a range of topics,
+including functional requirements, design considerations, and best practices for
+building and deploying decentralized web nodes.
+
+The contents of this companion guide include:
+
+- An overview of the DWN specification, including its purpose, scope, and key
+ features.
+- Functional requirements for implementing the DWN specification, including node
+ discovery, peer-to-peer networking, and data sharing protocols.
+- Design considerations for building decentralized web nodes that conform to the
+ DWN specification, including the use of decentralized storage systems like
+ IPFS, and cryptographic protocols for secure data sharing and verification.
+- Best practices for building and deploying decentralized web nodes, including
+ strategies for testing, debugging, and monitoring.
+
+This companion guide is intended to supplement the [formal DWN
+specification](https://identity.foundation/decentralized-web-node/spec/)
+developed by the DIF. By providing practical guidance on implementing the
+specification, this guide can help developers, architects, and solution
+providers to build decentralized web applications and services that promote
+greater privacy, security, and user control over their data.
+
+Overall, the Decentralized Web Node companion guide is a valuable resource for
+anyone who is interested in building decentralized web nodes that conform to the
+DWN specification.
+
+**STATUS:** PRE-DRAFT / IN PROGRESS
+
+### What Are Decentralized Web Nodes?
+
+The DWN specification is a set of standards for building and deploying
+decentralized web nodes, which are the building blocks of a decentralized web
+infrastructure.
+
+The DWN specification defines a set of protocols and APIs that enable
+decentralized web nodes to communicate and work together in a secure and
+interoperable way. This includes standards for data sharing, node discovery, and
+peer-to-peer networking.
+
+The DWN specification is designed to enable developers to build decentralized
+web applications and services that can operate independently of centralized
+infrastructure. This can help to improve the privacy, security, and resilience
+of the web, while also promoting greater user control over their data.
+
+The functional advantages of DWN's are that they are very good at scaling
+decentralized web apps. They enable multi-party data transactions with minimal
+overhead.
+
+Overall, the DWN specification is an important part of the DIF's work to promote
+the development of decentralized web technologies and standards. By providing a
+clear set of guidelines and best practices for building and deploying
+decentralized web nodes, the DWN specification can help to accelerate the
+adoption of a more decentralized and open web.
+
+## Target Audience
+
+This target audience for this document are those that have a strong technical
+background and experience in building web applications, as well as a good
+understanding of decentralized systems and protocols. They may also have
+experience with blockchain technologies, distributed computing, and peer-to-peer
+networking.
+
+Developers who intend to implement the DWN specification will need to have a
+good understanding of the protocols and APIs defined in the specification, as
+well as the underlying technologies that support it. This may include
+familiarity with decentralized storage systems like IPFS, as well as
+cryptographic protocols for secure data sharing and verification. This guide is
+intended to provide descriptive and functional color around some of the more
+formal specifications provided by the core specs.
+
+Architects and solution providers will also need to have a good understanding of
+the broader decentralized web ecosystem, including emerging standards and best
+practices. This can help to inform the design of decentralized web applications
+and services that are secure, scalable, and interoperable.
+
+Overall, the target audience for the DWN companion guide is a technical
+community that is committed to building a more decentralized and open web. By
+leveraging the DWN specification, developers, architects, and solution providers
+can help to accelerate the adoption of decentralized web technologies, and
+promote greater privacy, security, and user control over their data.
+
+## Scope
+
+This non-normative guide is intended to provide an overview of the functional
+requirements and design processes for implementing the Decentralized Web Node
+(DWN) specification developed by the Decentralized Identity Foundation (DIF).
+This guide is intended to be used by developers, architects, and solution
+providers who are interested in building decentralized web applications and
+services that conform to the DWN specification.
+
+The guide covers the following topics:
+
+- An overview of the DWN specification, including its purpose, scope, and key
+ features.
+- Functional requirements for implementing the DWN specification, including node
+ discovery, peer-to-peer networking, and data sharing protocols.
+- Design considerations for building decentralized web nodes that conform to the
+ DWN specification, including the use of decentralized storage systems like
+ IPFS, and cryptographic protocols for secure data sharing and verification.
+- Bestpractices for building and deploying decentralized web nodes, including
+ strategies for testing, debugging, and monitoring.
+
+This guide is intended to be a non-normative companion to the formal DWN
+specification developed by the DIF. While it is not a formal specification, this
+guide is intended to provide practical guidance for implementing the DWN
+specification in a way that promotes best practices and ensures interoperability
+with other decentralized web nodes.
+
+Overall, the scope of this non-normative guide is to provide developers,
+architects, and solution providers with a clear and practical overview of the
+functional requirements and design processes for implementing the DWN
+specification developed by the DIF.
+
+## Disclaimer
+
+This Decentralized Web Node (DWN) companion guide is a non-normative resource
+that is intended to provide practical guidance on implementing the DWN
+specification developed by the Decentralized Identity Foundation (DIF). This
+guide is not a formal specification, and as such, it is not intended to replace
+or supersede the DWN specification.
+
+The contents of this guide are based on the opinions and experiences of the
+authors, and are not necessarily endorsed by the DIF or any other organization.
+The guide is intended to be opinionated in the sense that it represents a
+particular perspective on how best to implement the DWN specification, based on
+the authors' experiences and insights.
+
+Readers are encouraged to use their own judgment and discretion when
+implementing the DWN specification, and to consider a range of approaches and
+best practices. This companion guide is not intended to be prescriptive or
+comprehensive, and readers are encouraged to consult other resources and experts
+in the field to inform their decisions.
+
+Overall, this companion guide is intended to provide a helpful resource for
+those interested in implementing the DWN specification, but it should be
+understood that the opinions and recommendations expressed in this guide are not
+the only or definitive way to approach decentralized web node design and
+implementation
+
+## Terminology
+
+The Terminology section of the Decentralized Web Node (DWN) companion guide is
+intended to provide a comprehensive and accessible reference for the key terms
+and concepts related to the DWN specification. This section aims to define
+important technical terms and concepts in a clear and concise manner, and to
+provide examples and illustrations where appropriate. The Terminology section is
+designed to be a useful resource for developers, architects, and solution
+providers who are new to the world of decentralized web technologies, as well as
+for those who are more experienced and looking for a refresher or clarification
+on certain terms and concepts.
+
+- **IPFS** :: A protocol, hypermedia and file sharing peer-to-peer network for
+ storing and sharing data in a distributed file system.
+- **DWN** :: A data storage and message relay mechanism entities can use to
+ locate public or private permissioned data related to a given Decentralized
+ Identifier (DID).
+- **DID** :: Decentralized identifiers (DIDs) are a type of globally unique
+ identifier that enables an entity to be identified in a manner that is
+ verifiable, persistent (as long as the DID controller desires), and does not
+ require the use of a centralized registry.
+- **[DAG
+ CBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md)**
+ :: DAG-CBOR is a codec that implements the IPLD Data Model as a subset of
+ CBOR, plus some additional constraints for hash consistent representations.
+- **Requests Objects** :: Request Objects are JSON object envelopes used to pass
+ messages to Decentralized Web Nodes.
+- **Collection** :: An interface of Decentralized Web Nodes provides a mechanism
+ to store data relative to shared schemas.
+- **Protocol** :: Protocols introduces a mechanism for declaratively encoding an
+ app or service’s underlying protocol rules, including segmentation of records,
+ relationships between records, data-level requirements, and constraints on how
+ participants interact with a protocol
+- **Hook** :: Web Hooks are one-way pushes of data to subscribed entities.
+- **[IANA Media
+ Type](https://www.iana.org/assignments/media-types/media-types.xhtml)** :: A
+ two-part identifier for file formats and format contents transmitted on the
+ Internet aka MIME type.
+- **JSON Web Signature ( JWS )** :: Content secured with digital signatures or
+ Message Authentication Codes (MACs) using JSON-based data structures
+- **Content Identifier (CID)** :: A label used to point to material in IPFS
+- **Message** :: All Decentralized Web Node messaging is transacted via Messages
+ JSON objects. These objects contain message execution parameters,
+ authorization material, authorization signatures, and signing/encryption
+ information
+
+## Technology Comparision
+
+There has been so much rapid development of Decentralized Storage technologies
+that it’s important to highlight the common aspects, and the differences with
+the goal of matching their unique features with the Use Case at hand.
+
+We will use the term “Personal and Application Data Storage” to denote the
+compared technologies whether they are a stack, libraries, protocols, or
+frameworks.
+
+This is by no means a comprehensive comparison, and we did not test these
+technologies at scale.
+
+### Technologies that are not Personal Data Stores
+
+
+#### **DIDComm** — https://didcomm.org/
+
+A DID-based, secured, transport-agnostic, peer-to-peer communications protocol.
+It lays the foundation to build domain/vertical/application specific protocols.
+
+#### **KERI** — https://keri.one/
+
+Enables the portability of Self-Sovereign Identities by eliminating the need
+for a ledger to establish a root of trust.
+
+#### **Nostr** — https://nostr.com/
+
+Nostr has gained some popularity as an open protocol that offers a censorship-resistant
+alternative to Twitter. It relies on relay servers that accept and store posts.
+A client or Dapp signs messages with the user’s private key and posts messages
+to as many relay servers as possible in order to keep the user’s content from
+being banned.
+Relay servers do not communicate with each other; thus the responsibility of
+replication is delegated to the Client application.
+Users are identified by their public key. That is, every post that is signed
+can be cryptographically verified.
+
+### Decentralized Storages that are not intrinsically Personal Data Stores
+
+#### **ChainSafe Storage** — https://storage.chainsafe.io/
+
+ChainSafe is an end-to-end, file-encrypting storage application. It persists
+symmetric-encrypted information on the IPFS/FileCoin network.
+It is meant to transition traditional Web 2.0 integrations with AWS S3 buckets
+to Web 3.0.
+
+#### **Fleek** — https://docs.fleek.co/
+
+Fleek is a multi-purpose set of technologies that allow Dapp Developers to host
+web applications on IPFS/FileCoin. It also provides general IPFS/FileCoin
+storage management. It is geared toward builders rather than individuals.
+Fleek offers Space and Space Daemon which are intended for building Privacy preserving
+Dapps. It is currently in Alpha.
+
+#### **Protocol Labs IPFS, FileCoin, FVM** — https://fvm.filecoin.io/
+
+IPFS is without a doubt the most successful storage protocol that decouples
+data from well-known servers, cloud storage, or any type of centralized storage.
+This is accomplished using Content Addressing (CID) and the segmenting of data
+in Direct Acyclic Graphs. In IPFS, the location of the data is its CID.
+FileCoin runs on top of IPFS and offers an incentive-based model for cold
+storage so that any entity that wants to profit from offering hardware
+resources may easily do so.
+
+The biggest drawback with IPFS/FileCoin is that once a rogue party has a hold
+of CIDs, the corresponding data is fully accessible. This paradigm forces
+client processes to encrypt data prior to storing it. Until now…
+
+Protocol Labs has now released the FileCoin Virtual Machine (FVM) network, an
+Ethereum-compatible VM. This means that Solidity developers can also develop in
+the new FVM.
+
+This technology offers the basic L1 plumbing that unleashes the potential for a
+new open data economy. In essence, this works as a decentralized operating system
+that orchestrates how data is persisted, retrieved, and governed.
+One of the basic features is the ability to bring computation to decentralized
+data. This means that L2 Compute Networks can encrypt and decrypt sensitive
+information, act as a gatekeeper, and offer the same features as the various
+Personal Data Stores discussed herein.
+
+It is worth mentioning that FVM uses WebAssembly as the bytecode for Smart
+Contracts. This means that any program that can be compiled into WebAssembly
+can be used for on-chain development.
+
+One of the most powerful features of these FVM smart contracts is the
+ability to define rules for data to obey, most importantly region and location
+for the storage of that data. This is important in order to remain
+compliant with regulations such as GDPR; e.g., data about EU citizens must remain
+within the borders of the European Community.
+
+FVM Consensus is achieved using their Interplanetary Consensus, and it is
+estimated that FVM will be able to handle transactions in the realm of one
+billion transactions per second (tps).
+
+### Personal Data Stores
+
+| Solid Pods | https://solidproject.org/ |
+| -------------- | ---------------------------------------------------------- |
+| Description | Decentralized Data Stores that rely on Linked Data to express identity and semantic data. The Pod is owned by an agent (Person, Organization, Group, Device, etc.) that is globally identified by a WebID. |
+| Specification | Open Specification incubated by Inrupt and now the [W3C](https://github.com/solid/specification/). |
+| Deployment | A Pod can be hosted by a Solid Pod Provider, or it can be user-deployed using any of its implementations in Node.js, PHP, or as a plugin for Nextcloud. |
+| Identity | WebID and its corresponding WebID Profile document. The WebID comes in the form of an HTTP URI, and it allows the linking of many agents in a web of trust using vocabularies such as [Friend of a Friend (FOAF)](http://xmlns.com/foaf/0.1/) semantics. |
+| Authentication | An agent uses its WebID to authenticate using the [SOLID-OIDC specification](https://solidproject.org/TR/oidc). A Solid Pod server becomes an OpenID provider. |
+| Authorization | Access to resources is managed by the Web Access Control system and its underlying Access Control List model. Authorizations are described using the ACL Ontology which is granular at the graph subject level. |
+| Transport | HTTP/1.1 through `GET`, `PUT`, `POST`, `PATCH`, and `DELETE` HTTP Methods. |
+| Schema / Data Representation | Data is encoded in graphs using N3 notation (a superset of RDF triples). Schemas are innate in RDF semantic ontologies. Any graphed relationship denotes a schema in its definition. |
+| Query Capabilities | The HTTP `GET` method allows for N3 Path Syntax. It is very similar to SPARQL 1.1 Property Path Syntax. |
+| License | MIT license and the Creative Commons Attribution 4.0 |
+
+
+| Ceramic and ComposeDB | https://ceramic.network/ |
+| ---------------------------- | -------------------------------------------- |
+| Description | Ceramic is a decentralized data network. Its foundations are laid on top of the Ceramic Event Driven Protocol. The infrastructure to build Personal Data Stores is offered by the Ceramic ComposeDB. ComposeDB replaces IDX and DID Data Store. |
+| Specification | Open Specification curated by Ceramic.Network |
+| Deployment | A ComposeDB instance is installed as part of Ceramic Node deployment. It can only be hosted in a Cloud environment. |
+| Identity | Decentralized Identifiers (DIDs) |
+| Authentication | Web3 Wallets and DID. |
+| Authorization | Object Capabilities |
+| Transport | GraphQL API over HTTP/1.1 |
+| Schema / Data Representation | API models are defined as GraphQL Schemas. The underlying data store uses graph nodes: Accounts and Documents. Relations are expressed as Edges. |
+| Query Capabilities | Partial GraphQL Queries. As of this writing, a query cannot be made against any data attributes. |
+| License |
+| [MIT](https://github.com/ceramicnetwork/js-ceramic/blob/develop/LICENSE-MIT)
+| and [Apache](https://github.com/ceramicnetwork/js-ceramic/blob/develop/LICENSE-APACHE) |
+
+| Atomic Data and Atomic Server | https://docs.atomicdata.dev/ |
+| ----------------------------- | ------------------------------------------- |
+| Description | Atomic offers a specification and a server to build JSON-LD for building privacy preserving applications. |
+| Specification | Open-Source Specification. The Atomic Server implementation in Rust is also open sourced. |
+| Deployment | It can be deployed in a Cloud environment or User-Hosted |
+| Identity | PKI |
+| Authentication | Json-AD Authentication Resource |
+| Authorization | Atomic Hierarchy Model |
+| Transport | WebSockets, HTTP 1/1 |
+| Schema / Data Representation | JSON-AD (JSON-Atomic Data). A variation of JSON-LD which supports the definition of schemas to provide type-safety. |
+| Query Capabilities | Atomic Paths, SPARQL |
+| License | [MIT](https://github.com/atomicdata-dev/atomic-server/blob/develop/LICENSE)|
+
+
+| Encrypted Data Vaults | https://identity.foundation/edv-spec/ |
+| --------------------- | --------------------------------------------------- |
+| Description | A specification with the goal of ensuring the privacy of an entity’s data by encrypting the data at rest |
+| Specification | Open-Source Specification incubated by DIF |
+| Deployment | [Pending] |
+| Identity | Support for various Identity models, DIDs being one such. |
+| Authentication | [Pending] |
+| Authorization | Authorization Capabilities |
+| Transport | HTTP 1/1, gRPC, Bluetooth |
+| Schema / Data Representation | [Pending] |
+| Query Capabilities | The goal is to provide Indexing and Querying capabilities. The working group is in the process of how deciding how this will be done. |
+| License | [Apache 2.0](https://github.com/decentralized-identity/edv-spec/blob/main/LICENSE.md)|
+
+| MyDex Personal Data Store | https://dev.mydex.org/connection-api/personal-data-store.html |
+| ------------------------- | ----------------------------------------------- |
+| Description | The MyDex Personal Data Store is a secure data vault residing in the cloud and hosted by MyDex Community Interest Company. An individual’s data is encrypted at rest using the individual’s key. MyDex does not have access to any key for decryption. |
+| Specification | Proprietary Specification |
+| Deployment | Offered as a SaaS solution |
+| Identity | MyDexID derived from PKI |
+| Authentication | SAML and OIDC |
+| Authorization | Proprietary Data Sharing Agreement |
+| Transport | REST over HTTP/1.1 |
+| Schema / Data Representation | JSON Formatted |
+| Query Capabilities | [Not found in documentation] |
+
+
+| The Hub of All Things | https://www.hubofallthings.com/ |
+| --------------------- | --------------------------------------------------- |
+| Description | The Hub of All Things is a service provided by DataSwift who developed the HAT Microserver, a personal web server and its accompanying PostgresQL database. A Hat Microserver segments data in namespaces, such that data from various verticals/domains/apps can live under the same instance. |
+| Specification | Proprietary Specification. HAT Microserver implementation in Scala is open sourced. |
+| Deployment | Offered as a SaaS solution |
+| Identity | HAT Universal ID |
+| Authentication | DataSwift One SSO |
+| Authorization | HAT Microserver Instructions Contract (HMIC) |
+| Transport | REST over HTTP 1.1 |
+| Schema / Data Representation | JSON Formatted |
+| Query Capabilities | [Not found in documentation] |
+
+| Peergos | https://https://peergos.org/ |
+| -------------- | ---------------------------------------------------------- |
+| Description | Peergos is a decentralised protocol and open-source platform for storage, social media and applications |
+| Specification | Open source [specification and implementations](https://book.peergos.org/architecture/spec.html) |
+| Deployment | Self Hosted or as a SaaS Multi-Tenant Service |
+| Identity | [PKI](https://book.peergos.org/security/pki.html) + [random keypairs](https://book.peergos.org/security/login.html) |
+| Authentication | Self-authenticated (signed and content addressed) & [S3 V4 Signatures for block level access control](https://book.peergos.org/security/bats.html)|
+| Authorization | [Cryptree](https://book.peergos.org/security/cryptree.html) based encryption and [Block access controls](https://book.peergos.org/security/bats.html) |
+| Transport | Transport agnostic. Apps have a local [HTTP RESTful API](https://book.peergos.org/features/apps.html) served from a ServiceWorker|
+| Schema / Data Representation | [DAG CBOR Encoded IPLD Objects and Raw Objects](https://book.peergos.org/security/bats.html). JSON Schema for app configuration. |
+| Query Capabilities | Peergos offers a RESTFul API with various capabilities described [here](https://book.peergos.org/features/apps.html). A few endpoints are directly specified. |
+| License | [GNU Affero General Public License v3.0](https://github.com/Peergos/Peergos/blob/master/Licence.txt)|
+
+| Decentralized Web Nodes | https://identity.foundation/decentralized-web-node/spec/ |
+| -------------- | ---------------------------------------------------------- |
+| Description | Decentralized Web Nodes are a mesh-like datastore construction that enable an entity to operate multiple nodes that sync to the same state across one another, enabling the owning entity to secure, manage, and transact their data with others without reliance on location or provider-specific infrastructure, interfaces, or routing mechanisms. |
+| Specification | [Open-Source Specification incubated by DIF](https://identity.foundation/decentralized-web-node/spec/) |
+| Deployment | Self Hosted or as a SaaS Multi-Tenant Service |
+| Identity | Decentralized Identifiers |
+| Authentication | DWN Aware Wallets / DID based |
+| Authorization | Permissions employ a capabilities-based architecture that allows for DID-based authorization and delegation of authorized capabilities to others. Derived key encryption with cryptree like encryption scheme. |
+| Transport | Transport Agnostic. Currently mostly implemented with HTTP. |
+| Schema / Data Representation | [Messages committed as IPLD DAG CBOR Encoded Object](https://identity.foundation/decentralized-web-node/spec/#signed-encrypted-data) with attached JSON Schema|
+| Query Capabilities | Protocols, Hooks, Records, Permissions |
+| License | |
+
+## Architecture and Components
+
+This section provides an overview of the high-level architecture of a DWN,
+including the different components that make up a typical DWN, such as the
+network layer, data storage layer, identity and access control layer, and the
+application layer. The section could also provide guidance on how to design and
+implement each of these components to conform to the DWN specification.
+
+## Node Discovery and Peer-to-Peer Networking
+
+This section provides detailed guidance on how to implement the node discovery
+and peer-to-peer networking protocols that are required for a DWN to function
+properly. This section could cover topics such as how to bootstrap a new node
+onto the network, how to maintain a list of known nodes, how to discover and
+connect to new peers, and how to propagate data across the network.
+
+## Data Sharing and Interoperability
+
+This section provides guidance on how to design and implement data sharing
+protocols that conform to the DWN specification, including the use of
+decentralized storage systems like IPFS and the InterPlanetary Linked Data
+(IPLD) format. This section could also cover strategies for promoting
+interoperability between different decentralized web nodes and data sharing
+protocols, such as the use of standardized data formats and metadata.
+
+## Security and Privacy
+
+This section provides guidance on how to design and implement security and
+privacy features that conform to the DWN specification, including the use of
+cryptographic protocols like Public Key Infrastructure (PKI) and Self-Sovereign
+Identity (SSI) for secure data sharing and verification. This section could also
+cover best practices for securing DWN infrastructure and protecting user data
+against common attacks and threats.
+
+## Testing and Debugging
+
+This section provides guidance on how to test and debug a DWN implementation,
+including strategies for testing individual components and the network as a
+whole, as well as tools and techniques for troubleshooting issues that may arise
+during development or deployment.
+
+## Deployment and Operations
+
+This section provides guidance on how to deploy and operate a DWN implementation
+in a production environment, including best practices for scaling and managing a
+distributed network, as well as tools and techniques for monitoring and managing
+network performance and reliability. This section could also cover strategies
+for maintaining backward compatibility and promoting interoperability with other
+decentralized web nodes and protocols.
+
+### Local Nodes, Remote Nodes, and Relays
+
+This section clarifies the role of a remote node, a local node, and a relay, with
+respect to a deployment. It is important to note that they are actually all the _same_
+thing, in that each is actually a DWN with no feature differences across these deployment types,
+but in practice a local node may be used slightly differently than a remote node.
+
+This section clarifies the difference in use between local and remote nodes, and what it means for a
+DWN to be a "relay".
+
+- **Local Node:** This could be a person's phone, computer, or other device that is
+ not expected to always be connected to the internet. For example, if Bob is
+ traveling in the mountains, his phone may be out of range, and so not be a
+ reliable device for services to connect to at scale.
+- **Remote Node:** Remote nodes are meant to be highly available and always
+ reachable from other services. If Bob takes a trip to the mountains and Jane
+ sends Bob a message, Jane would send the message to Bob's remote DWN, which
+ is always available, rather than directly to his local DWN (his phone), which is out of
+ range. This allows Bob to still interact with Jane and receive her
+ message, despite not being connected to the internet.
+- **Relay:** A relay is a way for a remote node to forward information it receives to a
+ local node, or to another remote node. When Jane sends a message to Bob's remote
+ DWN, Bob's remote DWN "relays" the message to Bob's local DWN, which allows
+ Bob to interact with his DWN locally.
+
+### Example Deployment (Simple)
+
+In this simple example, each actor has a remote (i.e a server) and local node
+(i.e a phone). As an example, you have a chat app with a remote and local node.
+Alice wants to send a message to Bob in this case, and Bob will reply with a
+message back.
+
+![DWN Simple
+Connection](https://identity.foundation/decentralized-web-node/spec/images/topology.svg)
+
+**Steps**
+
+0. Bob shares DID to Alice (via a QR code or some other transport)
+1. Alice Resolve's Bob's DID
+2. Alice sends a message to Bob's node discovered via a Service Endpoint in the
+ DID Document
+3. Bob's Node relays the Alice's message from the remote note to the local node.
+4. Bob resolves Alice's DID and finds the service endpoints
+5. Bob's local node ACTs on the message, sending a message back to Alice's Node
+6. Alice's remote node receives the message and relays it locally.
+
+### Example Deployment (Complex)
+
+## Miscellaneous
+
+### Example Use Cases
+
+### Real World Applications
+
+### DWN Adoption
+
+### Ecosystem interplay
+
+### Limitations and Other Considerations
+
+### Q&A
+
+#### General Questions
+
+- **How do you pronounce DWNs?**: We've heard a few ways to say it:
+
+ - As dawn : _dɔːn_
+ - D Web Node : _diː wɛb nəʊd_
+ - D W N : _diː ˈdʌbᵊljuː ɛn_
+
+- **How are DWNs different than SOLID Pods?** See the [Technology
+ Comparision](#technology-comparision) section for a detailed understanding of
+ how DWNs compare to different technology.
+
+- **For the base case, how many DWNs should I expect a particular person to
+ have?** As a general rule, a person can be expected to have a few DWNs. Possibly
+ more than 1 but less than 10. There may be cases which require more than 10.
+
+#### Security Questions
+
+- **Are there Data Privacy Considerations like GDPR? And how are they taken care
+ of in this kind of paradigm?** The full GDPR rights for individuals are: the
+ right to be informed, the right of access, the right to rectification, the
+ right to erasure, the right to restrict processing, the right to data
+ portability, the right to object and also rights around automated decision
+ making and profiling. Since DWN's are a personal data store where you control
+ your data, they are basically GDPR by default. See the [Security and
+ Privacy](#security-and-privacy-chatgpt) section for additional information.
+
+- **What is the best way to ensure that recipients of PII access via DWN are not
+ persistently storing the information using their own digital agent?** This
+ question is very dependent on the use case. It is up to the responsibility of
+ the DWN app/user to decide what data to give to whom. For sensitive data such
+ as PII, it would generally be recommended to give as little information as
+ possible and only when required. You can use Zero Knowledge Proofs (ZKP), if
+ you need to prove something over a DWN without sharing the actual data.
+
+#### Specification Questions
+
+- **How flexible/dynamic are the protocol control rules?** The Protocols
+ interface provides a way to define how another DWN may interact with your DWN.
+ This is different to RBAC controls that you would traditionally see in a
+ centralized control system. You can learn more about the protocols interface
+ [here](https://identity.foundation/decentralized-web-node/spec/#protocols).
+ Protocols introduces a mechanism for declaratively encoding an app or
+ service’s underlying protocol rules, including segmentation of records,
+ relationships between records, data-level requirements, and constraints on how
+ participants interact with a protocol.
+
+#### Technical Questions
+
+- **If I replicate DWNs for a service, how many DID's should be assigned?** A
+ single DID may point to multiple DWNs. There is a preference toward the first
+ service endpoint in the [resolution
+ array](https://identity.foundation/decentralized-web-node/spec/#resolution)
+- **What happens when there is asymmetry of resources across DWNs w.r.t sync?**
+ Although it is currently not supported, there eventually will be selective
+ sync that can allow you to filter certain things to sync across DWNs.
+- **How does latency impact sync?** All DWNs are built on a CRDT, so they will
+ eventually resolve without conflict, however you can expect that latency may
+ impact the speed of the resolution. Therefore, it's recommended to pick the
+ most highly available node for sending data across.
+- **How does the CRDT system work?** There are 2 levels of CRDT. The base layer,
+ object level CRDT, and the second layer, which is the data CRDT. These are
+ managed with commit strategies. See [here] for more information.
+ TODO: Spec does not discuss CRDT.
+- **Does a DWN run in the cloud, local, or both?** At the very least, they will
+ probably run locally, and there is a high likelihood that they will also run
+ in the cloud. The remote data will be available in case it needs to be very
+ available. Imagine for example you go on a hiking trip and you are out of
+ network. The DWN in the cloud would facilitate interactions that you would not
+ be able to do via your phone which is out of service.
+- **Do we write into an IPFS vs. IPLD Node?** DWN use IPLD as an encoding
+ format, but it's not required to throw out to the IPFS layer.
+- **What is IPLD?**IPLD is the data model of the content-addressable web. It
+ allows us to treat all hash-linked data structures as subsets of a unified
+ information space, unifying all data models that link data with hashes as
+ instances of IPLD.
+- **What if you want to use a DWN and don't want data on IPFS?** Not all DWNs
+ require IPFS.
+- **What are the main types of data store?** There are two types of datastores.
+ There's a `message store` that is intended to store metadata about the data
+ you're trying to store. Then there is a `datastore`, which actually has the
+ data you want to store.
+- **Does DWN allow or foresee applications that need cross user/company
+ synchronisation (e.g., DeFi applications that pose double-spend risks or
+ supply chain applications including international participants to be synced)?**
+ Eventually, yes, DWNs maybe able to facilitate those interactions.
+- **Would a DWN support the notion of a computational enclave that allows to
+ securely execute someone else’s code to access the DWN’s data, e.g., a
+ federated ML model that then the user can control what it sends back out to
+ the sender of the model?** You will be able to define access to a subset of
+ resources within a DWN based upon derived key permissions using Protocols.
+ This will give users the ability to access encrypted data on a DWN for only a
+ subset of a DWN, using a derived key. There is also a vision of DWNs being
+ able to work using homomorphic entryption, however this is an area of research now.
+
+### Reference Implementations
+
+- [TBD's JS SDK](https://github.com/TBD54566975/dwn-sdk-js) : Javascript sdk
+- [TBD's Web 5
+ Implementation](https://github.com/TBD54566975/incubating-web5-labs)
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..8eb7afa
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,3 @@
+# [Identity Hub](https://identity.foundation/identity-hub/)
+
+This specification describes identity hub's and their associated apis
diff --git a/guide/v0.0.1/index.html b/guide/v0.0.1/index.html
new file mode 100644
index 0000000..5e50588
--- /dev/null
+++ b/guide/v0.0.1/index.html
@@ -0,0 +1,1102 @@
+
+
+
+
+
+
+
+
+ Decentralized Web Node Companion Guide
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The Decentralized Web Node (DWN) companion guide is a non-normative guide that
+provides an overview of the functional requirements and design processes for
+implementing the DWN specification developed by the Decentralized Identity
+Foundation (DIF). This guide is intended to be used by developers, architects,
+and solution providers who are interested in building decentralized web
+applications and services that conform to the DWN specification.
+
This companion guide is not a formal
+specification, but
+rather a practical resource that provides guidance on implementing the DWN
+specification in a way that promotes best practices and ensures interoperability
+with other decentralized web nodes. The guide covers a range of topics,
+including functional requirements, design considerations, and best practices for
+building and deploying decentralized web nodes.
+
The contents of this companion guide include:
+
+
An overview of the DWN specification, including its purpose, scope, and key
+features.
+
Functional requirements for implementing the DWN specification, including node
+discovery, peer-to-peer networking, and data sharing protocols.
+
Design considerations for building decentralized web nodes that conform to the
+DWN specification, including the use of decentralized storage systems like
+IPFS, and cryptographic protocols for secure data sharing and verification.
+
Best practices for building and deploying decentralized web nodes, including
+strategies for testing, debugging, and monitoring.
+
+
This companion guide is intended to supplement the formal DWN
+specification
+developed by the DIF. By providing practical guidance on implementing the
+specification, this guide can help developers, architects, and solution
+providers to build decentralized web applications and services that promote
+greater privacy, security, and user control over their data.
+
Overall, the Decentralized Web Node companion guide is a valuable resource for
+anyone who is interested in building decentralized web nodes that conform to the
+DWN specification.
The DWN specification is a set of standards for building and deploying
+decentralized web nodes, which are the building blocks of a decentralized web
+infrastructure.
+
The DWN specification defines a set of protocols and APIs that enable
+decentralized web nodes to communicate and work together in a secure and
+interoperable way. This includes standards for data sharing, node discovery, and
+peer-to-peer networking.
+
The DWN specification is designed to enable developers to build decentralized
+web applications and services that can operate independently of centralized
+infrastructure. This can help to improve the privacy, security, and resilience
+of the web, while also promoting greater user control over their data.
+
The functional advantages of DWN’s are that they are very good at scaling
+decentralized web apps. They enable multi-party data transactions with minimal
+overhead.
+
Overall, the DWN specification is an important part of the DIF’s work to promote
+the development of decentralized web technologies and standards. By providing a
+clear set of guidelines and best practices for building and deploying
+decentralized web nodes, the DWN specification can help to accelerate the
+adoption of a more decentralized and open web.
This target audience for this document are those that have a strong technical
+background and experience in building web applications, as well as a good
+understanding of decentralized systems and protocols. They may also have
+experience with blockchain technologies, distributed computing, and peer-to-peer
+networking.
+
Developers who intend to implement the DWN specification will need to have a
+good understanding of the protocols and APIs defined in the specification, as
+well as the underlying technologies that support it. This may include
+familiarity with decentralized storage systems like IPFS, as well as
+cryptographic protocols for secure data sharing and verification. This guide is
+intended to provide descriptive and functional color around some of the more
+formal specifications provided by the core specs.
+
Architects and solution providers will also need to have a good understanding of
+the broader decentralized web ecosystem, including emerging standards and best
+practices. This can help to inform the design of decentralized web applications
+and services that are secure, scalable, and interoperable.
+
Overall, the target audience for the DWN companion guide is a technical
+community that is committed to building a more decentralized and open web. By
+leveraging the DWN specification, developers, architects, and solution providers
+can help to accelerate the adoption of decentralized web technologies, and
+promote greater privacy, security, and user control over their data.
This non-normative guide is intended to provide an overview of the functional
+requirements and design processes for implementing the Decentralized Web Node
+(DWN) specification developed by the Decentralized Identity Foundation (DIF).
+This guide is intended to be used by developers, architects, and solution
+providers who are interested in building decentralized web applications and
+services that conform to the DWN specification.
+
The guide covers the following topics:
+
+
An overview of the DWN specification, including its purpose, scope, and key
+features.
+
Functional requirements for implementing the DWN specification, including node
+discovery, peer-to-peer networking, and data sharing protocols.
+
Design considerations for building decentralized web nodes that conform to the
+DWN specification, including the use of decentralized storage systems like
+IPFS, and cryptographic protocols for secure data sharing and verification.
+
Bestpractices for building and deploying decentralized web nodes, including
+strategies for testing, debugging, and monitoring.
+
+
This guide is intended to be a non-normative companion to the formal DWN
+specification developed by the DIF. While it is not a formal specification, this
+guide is intended to provide practical guidance for implementing the DWN
+specification in a way that promotes best practices and ensures interoperability
+with other decentralized web nodes.
+
Overall, the scope of this non-normative guide is to provide developers,
+architects, and solution providers with a clear and practical overview of the
+functional requirements and design processes for implementing the DWN
+specification developed by the DIF.
This Decentralized Web Node (DWN) companion guide is a non-normative resource
+that is intended to provide practical guidance on implementing the DWN
+specification developed by the Decentralized Identity Foundation (DIF). This
+guide is not a formal specification, and as such, it is not intended to replace
+or supersede the DWN specification.
+
The contents of this guide are based on the opinions and experiences of the
+authors, and are not necessarily endorsed by the DIF or any other organization.
+The guide is intended to be opinionated in the sense that it represents a
+particular perspective on how best to implement the DWN specification, based on
+the authors’ experiences and insights.
+
Readers are encouraged to use their own judgment and discretion when
+implementing the DWN specification, and to consider a range of approaches and
+best practices. This companion guide is not intended to be prescriptive or
+comprehensive, and readers are encouraged to consult other resources and experts
+in the field to inform their decisions.
+
Overall, this companion guide is intended to provide a helpful resource for
+those interested in implementing the DWN specification, but it should be
+understood that the opinions and recommendations expressed in this guide are not
+the only or definitive way to approach decentralized web node design and
+implementation
The Terminology section of the Decentralized Web Node (DWN) companion guide is
+intended to provide a comprehensive and accessible reference for the key terms
+and concepts related to the DWN specification. This section aims to define
+important technical terms and concepts in a clear and concise manner, and to
+provide examples and illustrations where appropriate. The Terminology section is
+designed to be a useful resource for developers, architects, and solution
+providers who are new to the world of decentralized web technologies, as well as
+for those who are more experienced and looking for a refresher or clarification
+on certain terms and concepts.
+
+
IPFS :: A protocol, hypermedia and file sharing peer-to-peer network for
+storing and sharing data in a distributed file system.
+
DWN :: A data storage and message relay mechanism entities can use to
+locate public or private permissioned data related to a given Decentralized
+Identifier (DID).
+
DID :: Decentralized identifiers (DIDs) are a type of globally unique
+identifier that enables an entity to be identified in a manner that is
+verifiable, persistent (as long as the DID controller desires), and does not
+require the use of a centralized registry.
+
DAG
+CBOR
+:: DAG-CBOR is a codec that implements the IPLD Data Model as a subset of
+CBOR, plus some additional constraints for hash consistent representations.
+
Requests Objects :: Request Objects are JSON object envelopes used to pass
+messages to Decentralized Web Nodes.
+
Collection :: An interface of Decentralized Web Nodes provides a mechanism
+to store data relative to shared schemas.
+
Protocol :: Protocols introduces a mechanism for declaratively encoding an
+app or service’s underlying protocol rules, including segmentation of records,
+relationships between records, data-level requirements, and constraints on how
+participants interact with a protocol
+
Hook :: Web Hooks are one-way pushes of data to subscribed entities.
+
IANA Media
+Type :: A
+two-part identifier for file formats and format contents transmitted on the
+Internet aka MIME type.
+
JSON Web Signature ( JWS ) :: Content secured with digital signatures or
+Message Authentication Codes (MACs) using JSON-based data structures
+
Content Identifier (CID) :: A label used to point to material in IPFS
+
Message :: All Decentralized Web Node messaging is transacted via Messages
+JSON objects. These objects contain message execution parameters,
+authorization material, authorization signatures, and signing/encryption
+information
There has been so much rapid development of Decentralized Storage technologies
+that it’s important to highlight the common aspects, and the differences with
+the goal of matching their unique features with the Use Case at hand.
+
We will use the term “Personal and Application Data Storage” to denote the
+compared technologies whether they are a stack, libraries, protocols, or
+frameworks.
+
This is by no means a comprehensive comparison, and we did not test these
+technologies at scale.
A DID-based, secured, transport-agnostic, peer-to-peer communications protocol.
+It lays the foundation to build domain/vertical/application specific protocols.
Nostr has gained some popularity as an open protocol that offers a censorship-resistant
+alternative to Twitter. It relies on relay servers that accept and store posts.
+A client or Dapp signs messages with the user’s private key and posts messages
+to as many relay servers as possible in order to keep the user’s content from
+being banned.
+Relay servers do not communicate with each other; thus the responsibility of
+replication is delegated to the Client application.
+Users are identified by their public key. That is, every post that is signed
+can be cryptographically verified.
+
§ Decentralized Storages that are not intrinsically Personal Data Stores
ChainSafe is an end-to-end, file-encrypting storage application. It persists
+symmetric-encrypted information on the IPFS/FileCoin network.
+It is meant to transition traditional Web 2.0 integrations with AWS S3 buckets
+to Web 3.0.
Fleek is a multi-purpose set of technologies that allow Dapp Developers to host
+web applications on IPFS/FileCoin. It also provides general IPFS/FileCoin
+storage management. It is geared toward builders rather than individuals.
+Fleek offers Space and Space Daemon which are intended for building Privacy preserving
+Dapps. It is currently in Alpha.
IPFS is without a doubt the most successful storage protocol that decouples
+data from well-known servers, cloud storage, or any type of centralized storage.
+This is accomplished using Content Addressing (CID) and the segmenting of data
+in Direct Acyclic Graphs. In IPFS, the location of the data is its CID.
+FileCoin runs on top of IPFS and offers an incentive-based model for cold
+storage so that any entity that wants to profit from offering hardware
+resources may easily do so.
+
The biggest drawback with IPFS/FileCoin is that once a rogue party has a hold
+of CIDs, the corresponding data is fully accessible. This paradigm forces
+client processes to encrypt data prior to storing it. Until now…
+
Protocol Labs has now released the FileCoin Virtual Machine (FVM) network, an
+Ethereum-compatible VM. This means that Solidity developers can also develop in
+the new FVM.
+
This technology offers the basic L1 plumbing that unleashes the potential for a
+new open data economy. In essence, this works as a decentralized operating system
+that orchestrates how data is persisted, retrieved, and governed.
+One of the basic features is the ability to bring computation to decentralized
+data. This means that L2 Compute Networks can encrypt and decrypt sensitive
+information, act as a gatekeeper, and offer the same features as the various
+Personal Data Stores discussed herein.
+
It is worth mentioning that FVM uses WebAssembly as the bytecode for Smart
+Contracts. This means that any program that can be compiled into WebAssembly
+can be used for on-chain development.
+
One of the most powerful features of these FVM smart contracts is the
+ability to define rules for data to obey, most importantly region and location
+for the storage of that data. This is important in order to remain
+compliant with regulations such as GDPR; e.g., data about EU citizens must remain
+within the borders of the European Community.
+
FVM Consensus is achieved using their Interplanetary Consensus, and it is
+estimated that FVM will be able to handle transactions in the realm of one
+billion transactions per second (tps).
Decentralized Data Stores that rely on Linked Data to express identity and semantic data. The Pod is owned by an agent (Person, Organization, Group, Device, etc.) that is globally identified by a WebID.
+
+
+
Specification
+
Open Specification incubated by Inrupt and now the W3C.
+
+
+
Deployment
+
A Pod can be hosted by a Solid Pod Provider, or it can be user-deployed using any of its implementations in Node.js, PHP, or as a plugin for Nextcloud.
+
+
+
Identity
+
WebID and its corresponding WebID Profile document. The WebID comes in the form of an HTTP URI, and it allows the linking of many agents in a web of trust using vocabularies such as Friend of a Friend (FOAF) semantics.
+
+
+
Authentication
+
An agent uses its WebID to authenticate using the SOLID-OIDC specification. A Solid Pod server becomes an OpenID provider.
+
+
+
Authorization
+
Access to resources is managed by the Web Access Control system and its underlying Access Control List model. Authorizations are described using the ACL Ontology which is granular at the graph subject level.
+
+
+
Transport
+
HTTP/1.1 through GET, PUT, POST, PATCH, and DELETE HTTP Methods.
+
+
+
Schema / Data Representation
+
Data is encoded in graphs using N3 notation (a superset of RDF triples). Schemas are innate in RDF semantic ontologies. Any graphed relationship denotes a schema in its definition.
+
+
+
Query Capabilities
+
The HTTP GET method allows for N3 Path Syntax. It is very similar to SPARQL 1.1 Property Path Syntax.
+
+
+
License
+
MIT license and the Creative Commons Attribution 4.0
Ceramic is a decentralized data network. Its foundations are laid on top of the Ceramic Event Driven Protocol. The infrastructure to build Personal Data Stores is offered by the Ceramic ComposeDB. ComposeDB replaces IDX and DID Data Store.
+
+
+
Specification
+
Open Specification curated by Ceramic.Network
+
+
+
Deployment
+
A ComposeDB instance is installed as part of Ceramic Node deployment. It can only be hosted in a Cloud environment.
+
+
+
Identity
+
Decentralized Identifiers (DIDs)
+
+
+
Authentication
+
Web3 Wallets and DID.
+
+
+
Authorization
+
Object Capabilities
+
+
+
Transport
+
GraphQL API over HTTP/1.1
+
+
+
Schema / Data Representation
+
API models are defined as GraphQL Schemas. The underlying data store uses graph nodes: Accounts and Documents. Relations are expressed as Edges.
+
+
+
Query Capabilities
+
Partial GraphQL Queries. As of this writing, a query cannot be made against any data attributes.
The MyDex Personal Data Store is a secure data vault residing in the cloud and hosted by MyDex Community Interest Company. An individual’s data is encrypted at rest using the individual’s key. MyDex does not have access to any key for decryption.
The Hub of All Things is a service provided by DataSwift who developed the HAT Microserver, a personal web server and its accompanying PostgresQL database. A Hat Microserver segments data in namespaces, such that data from various verticals/domains/apps can live under the same instance.
+
+
+
Specification
+
Proprietary Specification. HAT Microserver implementation in Scala is open sourced.
Decentralized Web Nodes are a mesh-like datastore construction that enable an entity to operate multiple nodes that sync to the same state across one another, enabling the owning entity to secure, manage, and transact their data with others without reliance on location or provider-specific infrastructure, interfaces, or routing mechanisms.
Permissions employ a capabilities-based architecture that allows for DID-based authorization and delegation of authorized capabilities to others. Derived key encryption with cryptree like encryption scheme.
+
+
+
Transport
+
Transport Agnostic. Currently mostly implemented with HTTP.
This section provides an overview of the high-level architecture of a DWN,
+including the different components that make up a typical DWN, such as the
+network layer, data storage layer, identity and access control layer, and the
+application layer. The section could also provide guidance on how to design and
+implement each of these components to conform to the DWN specification.
This section provides detailed guidance on how to implement the node discovery
+and peer-to-peer networking protocols that are required for a DWN to function
+properly. This section could cover topics such as how to bootstrap a new node
+onto the network, how to maintain a list of known nodes, how to discover and
+connect to new peers, and how to propagate data across the network.
This section provides guidance on how to design and implement data sharing
+protocols that conform to the DWN specification, including the use of
+decentralized storage systems like IPFS and the InterPlanetary Linked Data
+(IPLD) format. This section could also cover strategies for promoting
+interoperability between different decentralized web nodes and data sharing
+protocols, such as the use of standardized data formats and metadata.
This section provides guidance on how to design and implement security and
+privacy features that conform to the DWN specification, including the use of
+cryptographic protocols like Public Key Infrastructure (PKI) and Self-Sovereign
+Identity (SSI) for secure data sharing and verification. This section could also
+cover best practices for securing DWN infrastructure and protecting user data
+against common attacks and threats.
This section provides guidance on how to test and debug a DWN implementation,
+including strategies for testing individual components and the network as a
+whole, as well as tools and techniques for troubleshooting issues that may arise
+during development or deployment.
This section provides guidance on how to deploy and operate a DWN implementation
+in a production environment, including best practices for scaling and managing a
+distributed network, as well as tools and techniques for monitoring and managing
+network performance and reliability. This section could also cover strategies
+for maintaining backward compatibility and promoting interoperability with other
+decentralized web nodes and protocols.
This section clarifies the role of a remote node, a local node, and a relay, with
+respect to a deployment. It is important to note that they are actually all the same
+thing, in that each is actually a DWN with no feature differences across these deployment types,
+but in practice a local node may be used slightly differently than a remote node.
+
This section clarifies the difference in use between local and remote nodes, and what it means for a
+DWN to be a “relay”.
+
+
Local Node: This could be a person’s phone, computer, or other device that is
+not expected to always be connected to the internet. For example, if Bob is
+traveling in the mountains, his phone may be out of range, and so not be a
+reliable device for services to connect to at scale.
+
Remote Node: Remote nodes are meant to be highly available and always
+reachable from other services. If Bob takes a trip to the mountains and Jane
+sends Bob a message, Jane would send the message to Bob’s remote DWN, which
+is always available, rather than directly to his local DWN (his phone), which is out of
+range. This allows Bob to still interact with Jane and receive her
+message, despite not being connected to the internet.
+
Relay: A relay is a way for a remote node to forward information it receives to a
+local node, or to another remote node. When Jane sends a message to Bob’s remote
+DWN, Bob’s remote DWN “relays” the message to Bob’s local DWN, which allows
+Bob to interact with his DWN locally.
In this simple example, each actor has a remote (i.e a server) and local node
+(i.e a phone). As an example, you have a chat app with a remote and local node.
+Alice wants to send a message to Bob in this case, and Bob will reply with a
+message back.
+
+
Steps
+
+
Bob shares DID to Alice (via a QR code or some other transport)
+
Alice Resolve’s Bob’s DID
+
Alice sends a message to Bob’s node discovered via a Service Endpoint in the
+DID Document
+
Bob’s Node relays the Alice’s message from the remote note to the local node.
+
Bob resolves Alice’s DID and finds the service endpoints
+
Bob’s local node ACTs on the message, sending a message back to Alice’s Node
+
Alice’s remote node receives the message and relays it locally.
How do you pronounce DWNs?: We’ve heard a few ways to say it:
+
+
As dawn : dɔːn
+
D Web Node : diː wɛb nəʊd
+
D W N : diː ˈdʌbᵊljuː ɛn
+
+
+
+
How are DWNs different than SOLID Pods? See the Technology
+Comparision section for a detailed understanding of
+how DWNs compare to different technology.
+
+
+
For the base case, how many DWNs should I expect a particular person to
+have? As a general rule, a person can be expected to have a few DWNs. Possibly
+more than 1 but less than 10. There may be cases which require more than 10.
Are there Data Privacy Considerations like GDPR? And how are they taken care
+of in this kind of paradigm? The full GDPR rights for individuals are: the
+right to be informed, the right of access, the right to rectification, the
+right to erasure, the right to restrict processing, the right to data
+portability, the right to object and also rights around automated decision
+making and profiling. Since DWN’s are a personal data store where you control
+your data, they are basically GDPR by default. See the Security and
+Privacy section for additional information.
+
+
+
What is the best way to ensure that recipients of PII access via DWN are not
+persistently storing the information using their own digital agent? This
+question is very dependent on the use case. It is up to the responsibility of
+the DWN app/user to decide what data to give to whom. For sensitive data such
+as PII, it would generally be recommended to give as little information as
+possible and only when required. You can use Zero Knowledge Proofs (ZKP), if
+you need to prove something over a DWN without sharing the actual data.
How flexible/dynamic are the protocol control rules? The Protocols
+interface provides a way to define how another DWN may interact with your DWN.
+This is different to RBAC controls that you would traditionally see in a
+centralized control system. You can learn more about the protocols interface
+here.
+Protocols introduces a mechanism for declaratively encoding an app or
+service’s underlying protocol rules, including segmentation of records,
+relationships between records, data-level requirements, and constraints on how
+participants interact with a protocol.
If I replicate DWNs for a service, how many DID’s should be assigned? A
+single DID may point to multiple DWNs. There is a preference toward the first
+service endpoint in the resolution
+array
+
What happens when there is asymmetry of resources across DWNs w.r.t sync?
+Although it is currently not supported, there eventually will be selective
+sync that can allow you to filter certain things to sync across DWNs.
+
How does latency impact sync? All DWNs are built on a CRDT, so they will
+eventually resolve without conflict, however you can expect that latency may
+impact the speed of the resolution. Therefore, it’s recommended to pick the
+most highly available node for sending data across.
+
How does the CRDT system work? There are 2 levels of CRDT. The base layer,
+object level CRDT, and the second layer, which is the data CRDT. These are
+managed with commit strategies. See [here] for more information.
+TODO: Spec does not discuss CRDT.
+
Does a DWN run in the cloud, local, or both? At the very least, they will
+probably run locally, and there is a high likelihood that they will also run
+in the cloud. The remote data will be available in case it needs to be very
+available. Imagine for example you go on a hiking trip and you are out of
+network. The DWN in the cloud would facilitate interactions that you would not
+be able to do via your phone which is out of service.
+
Do we write into an IPFS vs. IPLD Node? DWN use IPLD as an encoding
+format, but it’s not required to throw out to the IPFS layer.
+
**What is IPLD?**IPLD is the data model of the content-addressable web. It
+allows us to treat all hash-linked data structures as subsets of a unified
+information space, unifying all data models that link data with hashes as
+instances of IPLD.
+
What if you want to use a DWN and don’t want data on IPFS? Not all DWNs
+require IPFS.
+
What are the main types of data store? There are two types of datastores.
+There’s a message store that is intended to store metadata about the data
+you’re trying to store. Then there is a datastore, which actually has the
+data you want to store.
+
Does DWN allow or foresee applications that need cross user/company
+synchronisation (e.g., DeFi applications that pose double-spend risks or
+supply chain applications including international participants to be synced)?
+Eventually, yes, DWNs maybe able to facilitate those interactions.
+
Would a DWN support the notion of a computational enclave that allows to
+securely execute someone else’s code to access the DWN’s data, e.g., a
+federated ML model that then the user can control what it sends back out to
+the sender of the model? You will be able to define access to a subset of
+resources within a DWN based upon derived key permissions using Protocols.
+This will give users the ability to access encrypted data on a DWN for only a
+subset of a DWN, using a derived key. There is also a vision of DWNs being
+able to work using homomorphic entryption, however this is an area of research now.
Most digital activities between people, organizations, devices, and other entities
+require the exchange of messages and data. For entities to exchange messages and
+data for credential, app, or service flows, they need an interface through which
+to store, discover, and fetch data related to the flows and experiences they are
+participating in. A Decentralized Web Node (DWN) is a data storage and message relay mechanism
+entities can use to locate public or private permissioned data related to a given
+Decentralized Identifier (DID). Decentralized Web Nodes are a mesh-like datastore construction
+that enable an entity to operate multiple nodes that sync to the same state across
+one another, enabling the owning entity to secure, manage, and transact their data
+with others without reliance on location or provider-specific infrastructure,
+interfaces, or routing mechanisms.
Decentralized Web Node is a DRAFT specification under development within
+the Decentralized Identity Foundation (DIF). It is an active work item of the
+Secure Data Storage Working Group at DIF.
+It incorporates requirements and learnings from related work of many active industry players into a shared
+specification that meets the collective needs of the community.
+
The specification will be updated to incorporate feedback, from DIF members and
+the wider community, with a reference implementation being developed within DIF
+that exercises the features and requirements defined here. We encourage reviewers
+to submit GitHub Issues
+as the means by which to communicate feedback and contributions.
A decentralized personal and application data storage and message relay node,
+as defined in the DIF Decentralized Web Node specification. Users may have multiple
+Nodes that replicate their data between them.
+
Decentralized Identifiers
+
Unique ID URI string and PKI metadata document format for describing the
+cryptographic keys and other fundamental PKI values linked to a unique,
+user-controlled, self-sovereign identifier in a target system (e.g., blockchain,
+distributed ledger).
Decentralized Web Nodes are comprised of the following component layers, each of which is defined
+in this specification to ensure multiple Decentralized Web Node implementations can be used together and operate
+as a single logical unit for users.
All references to this section are out of date and will need to be updated.
+
+
All Decentralized Web Node messaging is transacted via Messages JSON objects. These objects contain message execution parameters, authorization material, authorization signatures, and signing/encryption information. For various purposes Messages rely on IPLD CIDs and DAG APIs.
In order to enable data replication features for a Decentralized Web Node, all Messages MUST be committed to an IPLD DAG in a tree allocated to the DID of the owner after all subtrees are composed and committed. The top-level of Message objects MUST be committed as a DAG CBOR encoded object.
+
+
Message objects MUST contain a recordId property, and its value MUST be the stringified Version 1 CID of the initial entry for the logical record in question, generated by running the the following Record ID Generation Process on the initial record entry:
+
+
Create a JSON object of the following composition:
+
+
The recordId CID generation object MUST contain a descriptorCid property, and its value MUST be the stringified Version 1 CID of the DAG CBOR encoded descriptor object.
Generate a Version 1 CID from the DAG CBOR encoded object and output it in its stringified form.
+
+
+
Message objects MAY contain a data property, and if present its value MUST be a base64Url encoded string of the Message’s data.
+
Message objects MUST contain a descriptor property, and its value MUST be an object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be a string that matches a Decentralized Web Node Interface.
+
The object MUST contain a method property, and its value MUST be a string that matches a Decentralized Web Node Interface method.
+
If the Message has data associated with it, passed directly via the data property of the Message or an external channel (e.g. IPFS fetch), the descriptor object MUST contain a dataCid property, and its value MUST be the stringified Version 1 CID of the DAG PB encoded data.
+
If the Message has data associated with it, passed directly via the data property of the Message object or through a channel external to the message object, the descriptor object MUST contain a dataFormat property, and its value MUST be a string that corresponds with a registered IANA Media Type data format (the most common being plain JSON, which is indicated by setting the value of the dataFormat property to application/json), or one of the following format strings pending registration:
+
Individual Interface methods may describe additional properties that the descriptor object MUST or MAY contain, which are detailed in the Interfaces section of the specification.
Some messages may require authorization material for processing them in accordance with the permissions a Decentralized Web Node owner has specified. If a message requires authorization it MUST include an authorization property with a value that is a [RFC7515] General JSON Web Signature (JWS), constructed as follows:
The JWS MUST include a protected property, and its value must be an object composed of the following values:
+
+
The object MUST include an alg property, and its value MUST be the string representing the algorithm used to verify the signature (as defined by the [RFC7515] JSON Web Signature specification).
+
The object MUST include a kid property, and its value MUST be a DID URL string identifying the key to be used in verifying the signature.
+
+
+
The JWS MUST include a payload property, and its value must be an object composed of the following values:
+
+
The object MUST include a descriptorCid property, and its value MUST be the stringified Version 1 CID of the DAG CBOR encoded descriptor object.
+
The object MAY include a permissionsGrantCid property, and its value MUST be the stringified Version 1 CID of the DAG CBOR encoded Permission Grant being invoked.
+
If attestation of an object is permitted, the payloadMAY include an attestationCid property, and its value MUST be the stringified Version 1 CID of the DAG CBOR encoded attestation string.
If there is no need or desire to sign or encrypt the content of a message (i.e. public repudiable data), the message descriptor object is the only property required in a Message (with any method-specific properties required). An optional data property may be passed at the Message level that contains the data associated with the message (when data is desired or required to be present for a given method invocation).
If the object is to be attested by a signer (e.g the Node owner via signature with their DID key), the object MUST contain the following additional properties to produce a [RFC7515] General JSON Web Signature (JWS):
The message generating party MUST construct the signed message object as follows:
+
+
The Message object MUST contain an attestation property, and its value MUST be a General object representation of a [RFC7515] JSON Web Signature composed as follows:
+
+
The object must include a payload property, and its value must be the stringified Version 1 CID of the DAG CBOR encoded descriptor object, whose composition is defined in the Message Descriptor section of this specification.
+
The object MUST include a protected property, and its value must be an object composed of the following values:
+
+
The object MUST include an alg property, and its value MUST be the string representing the algorithm used to verify the signature (as defined by the [RFC7515] JSON Web Signature specification).
+
The object MUST include a kid property, and its value MUST be a DID URL string identifying the key to be used in verifying the signature.
+
+
+
The object MUST include a signature property, and its value must be a signature string produced by signing the protected and payload values, in accordance with the [RFC7515] JSON Web Signature specification.
The message generating party MUST construct an encrypted message as follows:
+
+
The encryption property of the descriptor object MUST be set to the string label value of a Supported Encryption Format.
+
Generate an encrypted payload from the data conformant with the format specified in the encryption property…
+
Generate a Version 1 CID from the payload produced in Step 2 and let the dataCid property of the descriptor object be the stringified representation of the CID.
The message generating party MUST construct the signed and encrypted message as follows:
+
+
Follow the instructions described in the Encrypted Data section to add the required properties to the descriptor and produce a [RFC7516] JSON Web Encryption (JWE) object from the associated data.
+
Follow the instructions described in the Signed Data section to add an attestation property with a General object representation of a [RFC7515] JSON Web Signature as its value.
Responses from Interface method invocations are JSON objects that MUST be constructed as follows:
+
+
The object MAY have a status property if an error is produced from a general request-related issue, and if present its value MUST be an object composed of the following properties:
+
+
The status object MUST have a code property, and its value MUST be an integer set to the HTTP Status Code appropriate for the status of the response.
+
The status object MAY have a detail property, and if present its value MUST be a string that describes a terse summary of the status. It is recommended that the implementer set the message text to the standard title of the HTTP Status Code, when a title/message has already been defined for that code.
+
+
+
The object MAY have a replies property, and if present its value MUST be an array containing Message Result Objects for all messages that were included in the initiating request object. The Message Result ObjectsMUST be put in the index order that matches the index of each result’s corresponding request message. Message Result Objects are constructed as follows:
+
+
The object MUST have a status property, and its value MUST be an object composed of the following properties:
+
+
The status object MUST have a code property, and its value MUST be an integer set to the HTTP Status Code appropriate for the status of the response.
+
The status object MAY have a detail property, and if present its value MUST be a string that describes a terse summary of the status. It is recommended that the implementer set the message text to the standard title of the HTTP Status Code, when a title/message has already been defined for that code.
+
+
+
The object MAY have a entries property if the message request was successful. If present, its value MUST be the resulting message entries returned from the invocation of the corresponding message.
If any of the scenarios described in this section are encountered during general message processing, the implementation must include a request-level status property, and its value must be an object as defined below.
+
Target DID not found
+
If the DID targeted by a request object is not found within the Decentralized Web Node, the implementation MUST produce a request-level status with the code 404, and SHOULD use Target DID not found within the Decentralized Web Node as the status detail value.
{
+ "status":{
+ "code":404,
+ "detail":"Target DID not found within the Decentralized Web Node"
+ }
+}
+
+
+
General request-level processing errors
+
If a general request-level error in processing occurs that is not covered by one of the specific status cases above and prevent the implementation from correctly evaluating the request, the implementation MUST produce a request-level status with the code 500, and SHOULD use The request cannot not be processed as the status detail value.
If any of the scenarios described in this section are encountered during the processing of an individual message, the implementation must include a message-level status property, and its value must be an object as defined below.
+
Message succeeded for query/read-type interface that expects results
+
If a message is processed correctly and a set of result entries is expected, the implementation MUST include a message-level status object with its code property set to 200, and SHOULD use The message was successfully processed as the status detail value.
If a message is malformed or constructed with invalid properties/values, the implementation MUST include a message-level status object with its code property set to 400, and SHOULD use The message was malformed or improperly constructed as the status detail value.
{
+ "replies":[
+ {
+ "status":{"code":400,"detail":"The message was malformed or improperly constructed"}
+ }
+ ]
+}
+
+
+
Message failed authorization requirements
+
If a message fails to meet authorization requirements during processing, the implementation MUST include a message-level status object with its code property set to 401, and SHOULD use The message failed authorization requirements as the status detail value.
If a message attempts to invoke an interface method that is not the implementation does not support, the implementation MUST include a message-level status object with its code property set to 501, and SHOULD use The interface method is not implemented as the status detail value.
If the DWeb Node instance receiving the request has determined that the rate of resource consumption has exceeded its tolerances and cannot process the request, the instance MUST respond with the following status entry:
To maximize decentralized app and service interoperability, the Records interface of Decentralized Web Nodes
+provides a mechanism to store data relative to shared schemas. By storing data in accordance with a
+given schema, which may be well-known in a given vertical or industry, apps and services can leverage
+the same datasets across one another, enabling a cohesive, cross-platform, cross-device, cross-app
+experience for users.
RecordsRead messages are JSON objects that include general Message Descriptor properties and the following additional properties, which MUST be composed as follows:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Records.
+
The object MUST contain a method property, and its value MUST be the string Read.
+
The object MUST contain a messageTimestamp property, and its value
+MUST be of type string property, and its value MUST be an
+[RFC3339] ISO 8601 timestamp that MUST be set and interpreted
+as the time the RecordsRead record itself was created by the requester.
+
The object MUST contain a recordId property, and its value MUST be the recordId of the logical record with which the entry corresponds.
+
+
+
+
A reference of the json schema can be found in the
+schemas
+directory of the specification.
RecordsQuery messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Records.
+
The object MUST contain a method property, and its value MUST be the string Query.
+
The object MUST contain a messageTimestamp property, and its value
+MUST be of type string property, and its value MUST be an
+[RFC3339] ISO 8601 timestamp that MUST be set and interpreted
+as the time the RecordsQuery message was created by the requester.
+
The object MAY contain a filter property, and if present its value MUST be an object that MAY contain the following properties:
+
+
The object MAY contain a attester property representing the
+creator of the Record(s) did. If present its value MUST be a string in the form of a DID.
+
The object MAY contain a receipient property representing the
+recipient of the Record(s) DID If present its value MUST be a string in the form of a DID.
+
The object MAY contain a schema property, and if present its value Must be a URI string that indicates the schema of the associated data.
+
The object MAY contain a recordId property, and its value MUST be a Computed Record ID.
+
The object MAY contain a parentId property determined from the protocol definition, and if present its
+value MUST be a string that represents the computed record of
+the parent object.
+
The object MAY contain a contextId property, and its value MUST be the deterministic ID for a contextually linked set of objects.
+
The object MAY contain a dateCreated property. If present, it
+MUST include the from and to property described as a string range in the ISO 8601 format.
+
+
The from properties value MUST be of type string property, and its value MUST be an [RFC3339] ISO 8601 timestamp.
+
The to properties value MUST be of type string property, and its value MUST be an [RFC3339] ISO 8601 timestamp.
+
+
+
The object MAY contain a protocol property, and its value MUST be a URI that denotes the Protocol an object is a part of.
+
+
If the object contains a protocol property the object MUST also contain a protocolVersion property, and its value Must be a SemVer string that denotes the version of the Protocol the object is a part of.
+
+
+
The object MAY contain a dataFormat property, and its value MUST be a string that indicates the format of the data in accordance with its MIME type designation. The most common format is JSON, which is indicated by setting the value of the dataFormat property to application/json.
+
The object MAY contain a dateSort field, and if present its value MUST be one of the following strings:
+
+
createdAscending: return results in order from the earliest dateCreated value to the latest.
+
createdDescending: return results in order from the latest dateCreated value to the earliest.
+
publishedAscending: return results in order from the earliest datePublished value to the latest.
+
publishedDescending: return results in order from the latest datePublished value to the earliest.
RecordsWrite messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
+
+
The message object MUST contain a recordId property, and its value MUST be the recordId of the logical record the entry corresponds with. If the message is the initial entry for a new record, the value MUST be set to the resulting string from the Record ID Generation Process.
+
If the message object is attached to a Protocol, and its value MUST be a Computed Context ID. If the message is not attached to a Protocol, it MUST NOT contain a contextId property.
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Records.
+
The object MUST contain a method property, and its value MUST be the string Write.
+
The object MUST include a parentId property if the currently active entry for the record is a RecordsDelete or a CollectionWrite that has a declared a Commit Strategy. The object MUST NOT contain a parentId under any other circumstance. If present, the value of the parentId property MUST be the stringified Version 1 CID of the DAG CBOR encoded descriptor object of the previous RecordsWrite or RecordsDelete entry the message is intending to overwrite.
+
The object MAY contain a protocol property, and its value Must be a URI that denotes the Protocol an object is a part of.
+
+
If the object contains a protocol property the object MUST also contain a protocolVersion property, and its value Must be a SemVer string that denotes the version of the Protocol the object is a part of.
+
+
+
The object MAY contain a schema property, and if present its value Must be a URI string that indicates the schema of the associated data and MUST be treated as an immutable value for the lifetime of the logical record.
+
The object MAY contain a commitStrategy property, and if present its value Must be a string from the table of registered Commit Strategies.
+
The object MAY contain a published property, and if present its value Must be a boolean indicating the record’s publication state. A value of true indicates the record has been published for public queries and consumption without requiring authorization. A value of false or the absence of the property indicates the record MUST NOT be served in response to public queries that lack proper authorization.
+
The object MAY contain an encryption property, and if present its value Must be a string that matches one of the Supported Encryption Formats, indicating the encryption format with which the data is encrypted. The absence of this property indicates the data is not encrypted.
+
The object MUST contain a dateCreated property, and its value MUST be an [RFC3339] ISO 8601 timestamp that MUST be set and interpreted as the time the RecordsWrite was created by the DID owner or another permitted party.
+
The object MAY contain a datePublished property, and its value MUST be an [RFC3339] ISO 8601 timestamp that MUST be set and interpreted as the time the RecordsWrite was published by the DID owner or another permitted party.
RecordsDelete messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Records.
+
The object MUST contain a method property, and its value MUST be the string Delete.
+
The message object MUST contain a recordId property, and its value MUST be the recordId of the logical record the entry corresponds with.
+
The object MUST contain a messageTimestamp property, and its value
+MUST be of type string property, and its value MUST be an [RFC3339] ISO 8601 timestamp that MUST be set and interpreted
+as the time the RecordsDelete record itself was created by the requester.
Retained messages in the Records interface are those that may be stored against the specific record they are associated with. Within the Records interface the RecordsWrite, RecordsCommit, RecordsDelete messages are among the set that may be retained to determine the history and current data state of a record. A conforming implementation MUST perform the following steps to process retained messages:
IF no Initial Entry exists and cease any further processing.
+
+
+
ELSE the message may be an overwriting entry for the record; continue processing.
+
+
+
If a message is not the Initial Entry, its descriptorMUST contain a parentId to determine the entry’s position in the record’s lineage. If a parentId is present proceed with processing, else discard the record and cease processing.
+
Ensure all immutable values from the Initial Entry remained unchanged if present in the inbound message. If any have been mutated, discard the message and cease processing.
+
Retrieve the Latest Checkpoint Entry, which will be either the Initial Entry or the latest RecordsDelete, and compare the parentId value of the inbound message to the Entry ID of the Latest Checkpoint Entry derived from running the Record ID Generation Process on it. If the values match, proceed with processing, if the values do not match discard the message and cease processing.
+
If an existing RecordsWrite entry linked to the Latest Checkpoint Entryis not present and the dateCreated value of the inbound message is greater than the Latest Checkpoint Entry, store the message as the Latest Entry and cease processing, else discard the inbound message and cease processing.
+
If an exiting RecordsWrite entry linked to the Latest Checkpoint Entryis present all of the following conditions must be true:
+
+
The dateCreated value of the inbound message is greater than the existing RecordsWrite, or if the dateCreated values are the same, the Entry ID of the inbound message is greater than the existing entry when the Entry IDs of the two are compared lexicographically.
+
+
+
If all of the following conditions for Step 6 are true, store the inbound message as the Latest Entry and discard the existing RecordsWrite entry that was attached to the Latest Checkpoint Entry.
Ensure the record specified by the inbound message’s recordId exists. If it does not, discard the message and cease processing.
+
Ensure all immutable values from the Initial Entry remained unchanged if present in the inbound message. If any have been mutated, discard the message and cease processing.
+
Fetch the active RecordsDelete entry that exists for the record. If no such entry is present, proceed to the next step. If an active RecordsDelete entry for the record is present, the dateCreated value of the inbound message MUST be greater than the active RecordsDelete entry; if it is not, discard the message and cease processing.
DWeb Nodes are designed to act the substrate upon which a wide variety of decentralized applications and services can be written. With an interface like Records alone, a DWeb Node owner and those they permission can write isolated records, but that alone is not enough to support and facilitate decentralized apps. Protocols introduces a mechanism for declaratively encoding an app or service’s underlying protocol rules, including segmentation of records, relationships between records, data-level requirements, and constraints on how participants interact with a protocol. With the DWeb Node Protocols mechanism, one can model the underpinning protocols for a vast array of use cases in a way that enables interop-by-default between app implementations that ride on top of them.
ProtocolsConfigure messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
Protocol Definition objects are declarative rules within ProtocolConfigure messages that specify the types, relationships, and interactions that are permitted under a given protocol installed in a DWeb Node. Inbound callers who wish to interact with a protocol must adhere to these rules, which DWeb Nodes enforce.
The Protocols Definition object MUST contain a protocol property, and its value Must be a URI that denotes the Protocol the configuration pertains to.
+
The Protocols DefinitionMUST contain a published property, and its value Must be a boolean indicating the ProtocolConfiguration’s publication state.
+
The Protocols Definition object MUST contain a types property, and its value MUST be an object composed as follows:
+
+
The keys of the object MUST be a string that represents the underlying type.
+
The values representing those keys within the object MUST be an object composed as follows:
+
+
The object MUST contain a dataFormats property, and its value MUST be an array of strings that indicate the format of the data in accordance with its MIME type designation. The most common format is JSON, which is indicated by setting the value of the dataFormats property to ['application/json].
+
The object MAY contain a schema property, and if present its value MUST be a valid URI string that identifies the protocol the definition pertains to.
+
+
+
+
+
The Protocols Definition object MUST contain a structure property, and its value MUST be a Record Rules object whose keys match the labels defined in the Protocols Definition object. This object is recursive, allowing subsequent record relationships to be defined within. Labeled members of the object are composed as follows:
+
+
The keys of the object MUST be a string that matches one of the types
+
The values representing those keys within the object MUST be an object composed as follows:
+
+
The object MAY contain an $actions property and its value MUST be an array of rule set objects described as follows:
+
+
The object MUST contain a who property and it MUST have one of the following values:
+
+
anyone
+
author
+
recipient
+
+
+
The object MUST contain a can property and it MUST have a value of either read or write
+
The object MAY contain a of property and it MUST have a string value that references one of the types
When processing a ProtocolsConfigure message, a conforming implementation MUST perform the following steps:
+
+
If the message has a lastConfiguration property, ensure the referenced CID value links to a valid previous configuration for the specified protocol + version;
+
If the message:
+2a. Does not contain a protocolDefinition property, process the configuration as if the protocol + version is closed for interaction.
+2b. Does contain a protocolDefinition property, perform any indexing, setup, or optimization processes required to begin enforcing it within the implementation.
The Permissions interface provides a mechanism for external entities to request access
+to various data and functionality provided by a Decentralized Web Node. Permissions employ a
+capabilities-based architecture that allows for DID-based authorization and delegation
+of authorized capabilities to others, if allowed by the owner of a Decentralized Web Node.
PermissionsRequest messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Permissions.
+
The object MUST contain a method property, and its value MUST be the string Request.
+
The object MUST contain a grantedBy property, and its value MUST be the DID URI string of the party that is granting the permission.
+
The object MUST contain a grantedTo property, and its value MUST be the DID URI string of the party that is being granted the permission.
+
The object MAY contain a description property, and its value MUST be a string that the requesting party uses to communicate what the permission is being used for.
+
The object MUST contain a scope property, and its value Must be an object of the following properties:
+
+
The object MUST contain an interface property, and its value MUST be the interface the requesting party wants to invoke.
+
The object MUST contain a method property, and its value MUST be the interface method the requesting party wants to invoke.
+
The object MAY contain a schema property, and its value Must be a URI string that indicates the schema of the associated data.
+
The object MAY contain a protocol property, and its value Must be a URI that denotes the Protocol an object is a part of.
+
The object MAY contain a protocolVersion property, and its value Must be a SemVer string that denotes the version of the Protocol the object is a part of.
+
The object MAY contain a contextId property, and its value Must be the deterministic ID for a contextually linked set of objects.
+
+
+
The object MAY contain a conditions property, and its value Must be an object of the following properties:
+
+
The object MAY contain an attestation property, and if present its value Must be a string representing the signing conditions detailed below. If the property is not present it MUST be evaluated as if it were set to the value optional.
+
+
prohibited - the object MUST NOT be signed.
+
optional - the object MAY be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+
required - the object MUST be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+
+
+
The object MAY contain an encryption property, and if present its value Must be a string representing the encryption conditions detailed below. If the property is not present it MUST be evaluated as if it were set to the value optional.
+
+
optional - the object MAY be encrypted using the key provided by the owner of a Decentralized Web Node in the [RFC7516] JSON Web Encryption (JWE) format.
+
required - the object MUST be encrypted using the key provided by the owner of a Decentralized Web Node in the [RFC7516] JSON Web Encryption (JWE) format.
+
+
+
The object MAY contain a delegation property, and its value Must be a boolean, wherein true indicates the issuing party is allowing the grantee the ability to delegate the capability. A value of false or omission of the property MUST be evaluated as false, and indicates the grantee MUST NOT be allowed to delegate the capability.
+
The object MAY contain a publication property, and its value Must be a boolean, wherein true indicates the issuing party is allowing the grantee the ability to publish data tied to methods that support the public boolean value in their descriptor field sets. Conforming implementations MUST throw an error and fail to grant a permission if this property is present and the method does not support publication.
+
The object MAY contain a sharedAccess property, and its value Must be a boolean, wherein true indicates the requesting
+party wants the ability to use the permission against any object or data that aligns with the capability’s definition, regardless of which
+entity created the object or data. A value of false or omission of the property MUST be evaluated as false, and indicates the
+requesting party only needs the ability to invoke the permission against objects or data it creates.
+
+
+
+
+
The message object MUST contain an authorization property, which MUST be a JSON object as defined by the Message Authorization
+section of this specification, with the requirement that the kid and signatureMUST match the DID of the requesting party.
PermissionsGrant messages are JSON objects containing capabilities granted to parties that curtail the scope of permitted activities an invoker can perform. They are generated either in response to a PermissionsRequest message or optimistically by a user agent without an initiating PermissionsRequest. PermissionsGrant messages include general Message Descriptor properties and the following additional properties:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Permissions.
+
The object MUST contain a method property, and its value MUST be the string Grant.
+
The object MUST contain a permissionGrantId property, and its value MUST be an [RFC4122] UUID Version 4 string representing the reply object.
+
If the granted permission is in response to a PermissionRequest, the object MUST contain a permissionRequestId property, and its value MUST be the [RFC4122] UUID Version 4 string of the PermissionRequest object the permission is being granted in relation to.
+
The object MUST contain a grantedBy property, and its value MUST be the DID URI string of the party that is granting the permission.
+
The object MUST contain a grantedTo property, and its value MUST be the DID URI string of the party that is being granted the permission.
+
If the PermissionsGrant is a delegated permission, the object MUST contain a delegatedFrom property, and its value MUST be an [RFC4122] UUID Version 4 string matching the permissionGrantId of the PermissionsGrant it was delegated from.
+
The object MUST contain a expiry property, and its value MUST be a Unix epoch timestamp that can be used to trigger revocation activities.
+
The object MUST contain a scope property, and its value Must be an object of the following properties:
+
+
The object MUST contain an interface property, and its value MUST be the interface the requesting party wants to invoke.
+
The object MUST contain a method property, and its value MUST be the interface method the requesting party wants to invoke.
+
The object MAY contain a schema property, and its value Must be a URI string that indicates the schema of the associated data.
+
The object MAY contain a protocol property, and its value Must be a URI that denotes the Protocol an object is a part of.
+
The object MAY contain a protocolVersion property, and its value Must be a SemVer string that denotes the version of the Protocol the object is a part of.
+
The object MAY contain a recordId property, and its value Must be a UUID 4 string reference to an object.
+
The object MAY contain a contextId property, and its value Must be the deterministic ID for a contextually linked set of objects.
+
+
+
The object MAY contain a conditions property, and its value Must be an object of the following properties:
+
+
The object MAY contain an attestation property, and if present its value Must be a string representing the signing conditions detailed below. If the property is not present it MUST be evaluated as if it were set to the value optional.
+
+
prohibited - the object MUST NOT be signed.
+
optional - the object MAY be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+
required - the object MUST be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+
+
+
The object MAY contain an encryption property, and if present its value Must be a string representing the encryption conditions detailed below. If the property is not present it MUST be evaluated as if it were set to the value optional.
+
+
optional - the object MAY be encrypted using the key provided by the owner of a Decentralized Web Node in the [RFC7516] JSON Web Encryption (JWE) format.
+
required - the object MUST be encrypted using the key provided by the owner of a Decentralized Web Node in the [RFC7516] JSON Web Encryption (JWE) format.
+
+
+
The object MAY contain a delegation property, and its value Must be a boolean, wherein true indicates the issuing party is allowing the grantee the ability to delegate the capability. A value of false or omission of the property MUST be evaluated as false, and indicates the grantee MUST NOT be allowed to delegate the capability.
+
The object MAY contain a publication property, and its value Must be a boolean, wherein true indicates the issuing party is allowing the grantee the ability to publish data tied to methods that support the public boolean value in their descriptor field sets. Conforming implementations MUST throw an error and fail to grant a permission if this property is present and the method does not support publication.
+
The object MAY contain a sharedAccess property, and its value Must be a boolean, wherein true indicates the requesting
+party wants the ability to use the permission against any object or data that aligns with the capability’s definition, regardless of which
+entity created the object or data. A value of false or omission of the property MUST be evaluated as false, and indicates the
+requesting party only needs the ability to invoke the permission against objects or data it creates.
+
+
+
+
+
The message object MUST contain an authorization property, which MUST be a JSON object as defined by the Message Authorization
+section of this specification, with the requirement that the kid and signatureMUST match the DID of the requesting party.
+
The message MUST contain a data payload, which is a JSON Web Token representation of the granted permission, as defined in the Capability Objects section below.
+
The message MUST contain an encryptionKey property if the data transacted using the permission grant is to be encrypted, per the directives for encryption under the encryption field of the permission’s conditions. If present, the value of the encryptionKey property MUST be a [RFC7516] JSON Web Encryption (JWE) object that contains the encrypted key material required for an authorized party to decrypt the JWE represented by the dataCid value within the descriptor object.
The encryptionKey attribute of a PermissionsGrant is a [RFC7516] JSON Web Encryption (JWE) object that is composed as follows:
+
+
The kid field of the JWE header MUST be a DID URL that identifies the public key type designated for encryption in the DID Document of the PermissionGrant recipient.
+
The ciphertext field MUST be encrypted with the X25519 public key designated for encryption in the DID Document of the PermissionGrant recipient.
+
The data encrypted in the object’s ciphertext field MUST be the JSON Web Key (JWK) object representation of a AES-256 symmetric encryption key generated by the owner of the DWeb Node that will be used to encrypt the data transacted in relation to the associated PermissionGrant.
After generating a PermissionsGrant the user agent (e.g. wallet app with access to authoritative keys for a given DID) MUST commit the granted permission object to the Decentralized Web Node of the DID the grant was issued from. This will ensure that the permission is present when addressed in subsequent interface method invocations.
Once a user agent (e.g. wallet app with access to authoritative keys for a given DID) generates a PermissionsGrant for an entity to permit access to data and functionality, it is the responsibility of the user agent that generated the PermissionsGrant to deliver it to the entity that is the subject. To do this, the user agent MUST generate a Request that includes the PermissionsGrant and send it to the Decentralized Web Node of the subject it has been granted to, in accordance with the Resolution and Request Construction sections of this specification.
Revocation of a permission is the act of closing off any additional or invalid invocations of that permission. The Revoke interface method enables revocation of a permission via direct reference to the permission’s ID.
The Sync interface and its methods allow different Decentralized Web Nodes to communicate and sync on the state of the data they contain, including replication of messages and files.
A conforming implementation MUST be capable of encrypting and decrypting data stored in Decentralized Web Nodes using the following combinations of cryptographic schemes. Each scheme is a pair, wherein the symmetric keys are used to encrypt the data being protected, then subsequently shared with permitted recipients via encryption of the symmetric keys using the asymmetric key of each recipient.
A conforming implementation MUST be capable of encrypting and decrypting data stored in Decentralized Web Nodes using the following combinations of cryptographic schemes. Each scheme is a pair, wherein the symmetric keys are used to encrypt the data being protected, then subsequently shared with permitted recipients via encryption of the symmetric keys using the asymmetric key of each recipient.
Most digital activities between people, organizations, devices, and other entities
+require the exchange of messages and data. For entities to exchange messages and
+data for credential, app, or service flows, they need an interface through which
+to store, discover, and fetch data related to the flows and experiences they are
+participating in. A Decentralized Web Node (DWN) is a data storage and message relay mechanism
+entities can use to locate public or private permissioned data related to a given
+Decentralized Identifier (DID). Decentralized Web Nodes are a mesh-like datastore construction
+that enable an entity to operate multiple nodes that sync to the same state across
+one another, enabling the owning entity to secure, manage, and transact their data
+with others without reliance on location or provider-specific infrastructure,
+interfaces, or routing mechanisms.
Decentralized Web Node is a DRAFT specification under development within
+the Decentralized Identity Foundation (DIF). It is an active work item of the
+Secure Data Storage Working Group at DIF.
+It incorporates requirements and learnings from related work of many active industry players into a shared
+specification that meets the collective needs of the community.
+
The specification will be updated to incorporate feedback, from DIF members and
+the wider community, with a reference implementation being developed within DIF
+that exercises the features and requirements defined here. We encourage reviewers
+to submit GitHub Issues
+as the means by which to communicate feedback and contributions.
A decentralized personal and application data storage and message relay node,
+as defined in the DIF Decentralized Web Node specification. Users may have multiple
+Nodes that replicate their data between them.
+
Decentralized Identifiers
+
Unique ID URI string and PKI metadata document format for describing the
+cryptographic keys and other fundamental PKI values linked to a unique,
+user-controlled, self-sovereign identifier in a target system (e.g., blockchain,
+distributed ledger).
Decentralized Web Nodes are comprised of the following component layers, each of which is defined
+in this specification to ensure multiple Decentralized Web Node implementations can be used together and operate
+as a single logical unit for users.
All references to this section are out of date and will need to be updated.
+
+
All Decentralized Web Node messaging is transacted via Messages JSON objects. These objects contain message execution parameters, authorization material, authorization signatures, and signing/encryption information. For various purposes Messages rely on IPLD CIDs and DAG APIs.
In order to enable data replication features for a Decentralized Web Node, all Messages MUST be committed to an IPLD DAG in a tree allocated to the DID of the owner after all subtrees are composed and committed. The top-level of Message objects MUST be committed as a DAG CBOR encoded object.
+
+
Message objects MUST contain a recordId property, and its value MUST be the stringified Version 1 CID of the initial entry for the logical record in question, generated by running the the following Record ID Generation Process on the initial record entry:
+
+
Create a JSON object of the following composition:
+
+
The recordId CID generation object MUST contain a descriptorCid property, and its value MUST be the stringified Version 1 CID of the DAG CBOR encoded descriptor object.
Generate a Version 1 CID from the DAG CBOR encoded object and output it in its stringified form.
+
+
+
Message objects MAY contain a data property, and if present its value MUST be a base64Url encoded string of the Message’s data.
+
Message objects MUST contain a descriptor property, and its value MUST be an object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be a string that matches a Decentralized Web Node Interface.
+
The object MUST contain a method property, and its value MUST be a string that matches a Decentralized Web Node Interface method.
+
If the Message has data associated with it, passed directly via the data property of the Message or an external channel (e.g. IPFS fetch), the descriptor object MUST contain a dataCid property, and its value MUST be the stringified Version 1 CID of the DAG PB encoded data.
+
If the Message has data associated with it, passed directly via the data property of the Message object or through a channel external to the message object, the descriptor object MUST contain a dataFormat property, and its value MUST be a string that corresponds with a registered IANA Media Type data format (the most common being plain JSON, which is indicated by setting the value of the dataFormat property to application/json), or one of the following format strings pending registration:
+
Individual Interface methods may describe additional properties that the descriptor object MUST or MAY contain, which are detailed in the Interfaces section of the specification.
Some messages may require authorization material for processing them in accordance with the permissions a Decentralized Web Node owner has specified. If a message requires authorization it MUST include an authorization property with a value that is a [RFC7515] General JSON Web Signature (JWS), constructed as follows:
The JWS MUST include a protected property, and its value must be an object composed of the following values:
+
+
The object MUST include an alg property, and its value MUST be the string representing the algorithm used to verify the signature (as defined by the [RFC7515] JSON Web Signature specification).
+
The object MUST include a kid property, and its value MUST be a DID URL string identifying the key to be used in verifying the signature.
+
+
+
The JWS MUST include a payload property, and its value must be an object composed of the following values:
+
+
The object MUST include a descriptorCid property, and its value MUST be the stringified Version 1 CID of the DAG CBOR encoded descriptor object.
+
The object MAY include a permissionsGrantCid property, and its value MUST be the stringified Version 1 CID of the DAG CBOR encoded Permission Grant being invoked.
+
If attestation of an object is permitted, the payloadMAY include an attestationCid property, and its value MUST be the stringified Version 1 CID of the DAG CBOR encoded attestation string.
If there is no need or desire to sign or encrypt the content of a message (i.e. public repudiable data), the message descriptor object is the only property required in a Message (with any method-specific properties required). An optional data property may be passed at the Message level that contains the data associated with the message (when data is desired or required to be present for a given method invocation).
If the object is to be attested by a signer (e.g the Node owner via signature with their DID key), the object MUST contain the following additional properties to produce a [RFC7515] General JSON Web Signature (JWS):
The message generating party MUST construct the signed message object as follows:
+
+
The Message object MUST contain an attestation property, and its value MUST be a General object representation of a [RFC7515] JSON Web Signature composed as follows:
+
+
The object must include a payload property, and its value must be the stringified Version 1 CID of the DAG CBOR encoded descriptor object, whose composition is defined in the Message Descriptor section of this specification.
+
The object MUST include a protected property, and its value must be an object composed of the following values:
+
+
The object MUST include an alg property, and its value MUST be the string representing the algorithm used to verify the signature (as defined by the [RFC7515] JSON Web Signature specification).
+
The object MUST include a kid property, and its value MUST be a DID URL string identifying the key to be used in verifying the signature.
+
+
+
The object MUST include a signature property, and its value must be a signature string produced by signing the protected and payload values, in accordance with the [RFC7515] JSON Web Signature specification.
The message generating party MUST construct an encrypted message as follows:
+
+
The encryption property of the descriptor object MUST be set to the string label value of a Supported Encryption Format.
+
Generate an encrypted payload from the data conformant with the format specified in the encryption property…
+
Generate a Version 1 CID from the payload produced in Step 2 and let the dataCid property of the descriptor object be the stringified representation of the CID.
The message generating party MUST construct the signed and encrypted message as follows:
+
+
Follow the instructions described in the Encrypted Data section to add the required properties to the descriptor and produce a [RFC7516] JSON Web Encryption (JWE) object from the associated data.
+
Follow the instructions described in the Signed Data section to add an attestation property with a General object representation of a [RFC7515] JSON Web Signature as its value.
Responses from Interface method invocations are JSON objects that MUST be constructed as follows:
+
+
The object MAY have a status property if an error is produced from a general request-related issue, and if present its value MUST be an object composed of the following properties:
+
+
The status object MUST have a code property, and its value MUST be an integer set to the HTTP Status Code appropriate for the status of the response.
+
The status object MAY have a detail property, and if present its value MUST be a string that describes a terse summary of the status. It is recommended that the implementer set the message text to the standard title of the HTTP Status Code, when a title/message has already been defined for that code.
+
+
+
The object MAY have a replies property, and if present its value MUST be an array containing Message Result Objects for all messages that were included in the initiating request object. The Message Result ObjectsMUST be put in the index order that matches the index of each result’s corresponding request message. Message Result Objects are constructed as follows:
+
+
The object MUST have a status property, and its value MUST be an object composed of the following properties:
+
+
The status object MUST have a code property, and its value MUST be an integer set to the HTTP Status Code appropriate for the status of the response.
+
The status object MAY have a detail property, and if present its value MUST be a string that describes a terse summary of the status. It is recommended that the implementer set the message text to the standard title of the HTTP Status Code, when a title/message has already been defined for that code.
+
+
+
The object MAY have a entries property if the message request was successful. If present, its value MUST be the resulting message entries returned from the invocation of the corresponding message.
If any of the scenarios described in this section are encountered during general message processing, the implementation must include a request-level status property, and its value must be an object as defined below.
+
Target DID not found
+
If the DID targeted by a request object is not found within the Decentralized Web Node, the implementation MUST produce a request-level status with the code 404, and SHOULD use Target DID not found within the Decentralized Web Node as the status detail value.
{
+ "status":{
+ "code":404,
+ "detail":"Target DID not found within the Decentralized Web Node"
+ }
+}
+
+
+
General request-level processing errors
+
If a general request-level error in processing occurs that is not covered by one of the specific status cases above and prevent the implementation from correctly evaluating the request, the implementation MUST produce a request-level status with the code 500, and SHOULD use The request cannot not be processed as the status detail value.
If any of the scenarios described in this section are encountered during the processing of an individual message, the implementation must include a message-level status property, and its value must be an object as defined below.
+
Message succeeded for query/read-type interface that expects results
+
If a message is processed correctly and a set of result entries is expected, the implementation MUST include a message-level status object with its code property set to 200, and SHOULD use The message was successfully processed as the status detail value.
If a message is malformed or constructed with invalid properties/values, the implementation MUST include a message-level status object with its code property set to 400, and SHOULD use The message was malformed or improperly constructed as the status detail value.
{
+ "replies":[
+ {
+ "status":{"code":400,"detail":"The message was malformed or improperly constructed"}
+ }
+ ]
+}
+
+
+
Message failed authorization requirements
+
If a message fails to meet authorization requirements during processing, the implementation MUST include a message-level status object with its code property set to 401, and SHOULD use The message failed authorization requirements as the status detail value.
If a message attempts to invoke an interface method that is not the implementation does not support, the implementation MUST include a message-level status object with its code property set to 501, and SHOULD use The interface method is not implemented as the status detail value.
If the DWeb Node instance receiving the request has determined that the rate of resource consumption has exceeded its tolerances and cannot process the request, the instance MUST respond with the following status entry:
To maximize decentralized app and service interoperability, the Records interface of Decentralized Web Nodes
+provides a mechanism to store data relative to shared schemas. By storing data in accordance with a
+given schema, which may be well-known in a given vertical or industry, apps and services can leverage
+the same datasets across one another, enabling a cohesive, cross-platform, cross-device, cross-app
+experience for users.
RecordsRead messages are JSON objects that include general Message Descriptor properties and the following additional properties, which MUST be composed as follows:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Records.
+
The object MUST contain a method property, and its value MUST be the string Read.
+
The object MUST contain a messageTimestamp property, and its value
+MUST be of type string property, and its value MUST be an
+[RFC3339] ISO 8601 timestamp that MUST be set and interpreted
+as the time the RecordsRead record itself was created by the requester.
+
The object MUST contain a recordId property, and its value MUST be the recordId of the logical record with which the entry corresponds.
+
+
+
+
A reference of the json schema can be found in the
+schemas
+directory of the specification.
RecordsQuery messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Records.
+
The object MUST contain a method property, and its value MUST be the string Query.
+
The object MUST contain a messageTimestamp property, and its value
+MUST be of type string property, and its value MUST be an
+[RFC3339] ISO 8601 timestamp that MUST be set and interpreted
+as the time the RecordsQuery message was created by the requester.
+
The object MAY contain a filter property, and if present its value MUST be an object that MAY contain the following properties:
+
+
The object MAY contain a attester property representing the
+creator of the Record(s) did. If present its value MUST be a string in the form of a DID.
+
The object MAY contain a receipient property representing the
+recipient of the Record(s) DID If present its value MUST be a string in the form of a DID.
+
The object MAY contain a schema property, and if present its value Must be a URI string that indicates the schema of the associated data.
+
The object MAY contain a recordId property, and its value MUST be a Computed Record ID.
+
The object MAY contain a parentId property determined from the protocol definition, and if present its
+value MUST be a string that represents the computed record of
+the parent object.
+
The object MAY contain a contextId property, and its value MUST be the deterministic ID for a contextually linked set of objects.
+
The object MAY contain a dateCreated property. If present, it
+MUST include the from and to property described as a string range in the ISO 8601 format.
+
+
The from properties value MUST be of type string property, and its value MUST be an [RFC3339] ISO 8601 timestamp.
+
The to properties value MUST be of type string property, and its value MUST be an [RFC3339] ISO 8601 timestamp.
+
+
+
The object MAY contain a protocol property, and its value MUST be a URI that denotes the Protocol an object is a part of.
+
+
If the object contains a protocol property the object MUST also contain a protocolVersion property, and its value Must be a SemVer string that denotes the version of the Protocol the object is a part of.
+
+
+
The object MAY contain a dataFormat property, and its value MUST be a string that indicates the format of the data in accordance with its MIME type designation. The most common format is JSON, which is indicated by setting the value of the dataFormat property to application/json.
+
The object MAY contain a dateSort field, and if present its value MUST be one of the following strings:
+
+
createdAscending: return results in order from the earliest dateCreated value to the latest.
+
createdDescending: return results in order from the latest dateCreated value to the earliest.
+
publishedAscending: return results in order from the earliest datePublished value to the latest.
+
publishedDescending: return results in order from the latest datePublished value to the earliest.
RecordsWrite messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
+
+
The message object MUST contain a recordId property, and its value MUST be the recordId of the logical record the entry corresponds with. If the message is the initial entry for a new record, the value MUST be set to the resulting string from the Record ID Generation Process.
+
If the message object is attached to a Protocol, and its value MUST be a Computed Context ID. If the message is not attached to a Protocol, it MUST NOT contain a contextId property.
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Records.
+
The object MUST contain a method property, and its value MUST be the string Write.
+
The object MUST include a parentId property if the currently active entry for the record is a RecordsDelete or a CollectionWrite that has a declared a Commit Strategy. The object MUST NOT contain a parentId under any other circumstance. If present, the value of the parentId property MUST be the stringified Version 1 CID of the DAG CBOR encoded descriptor object of the previous RecordsWrite or RecordsDelete entry the message is intending to overwrite.
+
The object MAY contain a protocol property, and its value Must be a URI that denotes the Protocol an object is a part of.
+
+
If the object contains a protocol property the object MUST also contain a protocolVersion property, and its value Must be a SemVer string that denotes the version of the Protocol the object is a part of.
+
+
+
The object MAY contain a schema property, and if present its value Must be a URI string that indicates the schema of the associated data and MUST be treated as an immutable value for the lifetime of the logical record.
+
The object MAY contain a commitStrategy property, and if present its value Must be a string from the table of registered Commit Strategies.
+
The object MAY contain a published property, and if present its value Must be a boolean indicating the record’s publication state. A value of true indicates the record has been published for public queries and consumption without requiring authorization. A value of false or the absence of the property indicates the record MUST NOT be served in response to public queries that lack proper authorization.
+
The object MAY contain an encryption property, and if present its value Must be a string that matches one of the Supported Encryption Formats, indicating the encryption format with which the data is encrypted. The absence of this property indicates the data is not encrypted.
+
The object MUST contain a dateCreated property, and its value MUST be an [RFC3339] ISO 8601 timestamp that MUST be set and interpreted as the time the RecordsWrite was created by the DID owner or another permitted party.
+
The object MAY contain a datePublished property, and its value MUST be an [RFC3339] ISO 8601 timestamp that MUST be set and interpreted as the time the RecordsWrite was published by the DID owner or another permitted party.
RecordsDelete messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Records.
+
The object MUST contain a method property, and its value MUST be the string Delete.
+
The message object MUST contain a recordId property, and its value MUST be the recordId of the logical record the entry corresponds with.
+
The object MUST contain a messageTimestamp property, and its value
+MUST be of type string property, and its value MUST be an [RFC3339] ISO 8601 timestamp that MUST be set and interpreted
+as the time the RecordsDelete record itself was created by the requester.
Retained messages in the Records interface are those that may be stored against the specific record they are associated with. Within the Records interface the RecordsWrite, RecordsCommit, RecordsDelete messages are among the set that may be retained to determine the history and current data state of a record. A conforming implementation MUST perform the following steps to process retained messages:
IF no Initial Entry exists and cease any further processing.
+
+
+
ELSE the message may be an overwriting entry for the record; continue processing.
+
+
+
If a message is not the Initial Entry, its descriptorMUST contain a parentId to determine the entry’s position in the record’s lineage. If a parentId is present proceed with processing, else discard the record and cease processing.
+
Ensure all immutable values from the Initial Entry remained unchanged if present in the inbound message. If any have been mutated, discard the message and cease processing.
+
Retrieve the Latest Checkpoint Entry, which will be either the Initial Entry or the latest RecordsDelete, and compare the parentId value of the inbound message to the Entry ID of the Latest Checkpoint Entry derived from running the Record ID Generation Process on it. If the values match, proceed with processing, if the values do not match discard the message and cease processing.
+
If an existing RecordsWrite entry linked to the Latest Checkpoint Entryis not present and the dateCreated value of the inbound message is greater than the Latest Checkpoint Entry, store the message as the Latest Entry and cease processing, else discard the inbound message and cease processing.
+
If an exiting RecordsWrite entry linked to the Latest Checkpoint Entryis present all of the following conditions must be true:
+
+
The dateCreated value of the inbound message is greater than the existing RecordsWrite, or if the dateCreated values are the same, the Entry ID of the inbound message is greater than the existing entry when the Entry IDs of the two are compared lexicographically.
+
+
+
If all of the following conditions for Step 6 are true, store the inbound message as the Latest Entry and discard the existing RecordsWrite entry that was attached to the Latest Checkpoint Entry.
Ensure the record specified by the inbound message’s recordId exists. If it does not, discard the message and cease processing.
+
Ensure all immutable values from the Initial Entry remained unchanged if present in the inbound message. If any have been mutated, discard the message and cease processing.
+
Fetch the active RecordsDelete entry that exists for the record. If no such entry is present, proceed to the next step. If an active RecordsDelete entry for the record is present, the dateCreated value of the inbound message MUST be greater than the active RecordsDelete entry; if it is not, discard the message and cease processing.
DWeb Nodes are designed to act the substrate upon which a wide variety of decentralized applications and services can be written. With an interface like Records alone, a DWeb Node owner and those they permission can write isolated records, but that alone is not enough to support and facilitate decentralized apps. Protocols introduces a mechanism for declaratively encoding an app or service’s underlying protocol rules, including segmentation of records, relationships between records, data-level requirements, and constraints on how participants interact with a protocol. With the DWeb Node Protocols mechanism, one can model the underpinning protocols for a vast array of use cases in a way that enables interop-by-default between app implementations that ride on top of them.
ProtocolsConfigure messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
Protocol Definition objects are declarative rules within ProtocolConfigure messages that specify the types, relationships, and interactions that are permitted under a given protocol installed in a DWeb Node. Inbound callers who wish to interact with a protocol must adhere to these rules, which DWeb Nodes enforce.
The Protocols Definition object MUST contain a protocol property, and its value Must be a URI that denotes the Protocol the configuration pertains to.
+
The Protocols DefinitionMUST contain a published property, and its value Must be a boolean indicating the ProtocolConfiguration’s publication state.
+
The Protocols Definition object MUST contain a types property, and its value MUST be an object composed as follows:
+
+
The keys of the object MUST be a string that represents the underlying type.
+
The values representing those keys within the object MUST be an object composed as follows:
+
+
The object MUST contain a dataFormats property, and its value MUST be an array of strings that indicate the format of the data in accordance with its MIME type designation. The most common format is JSON, which is indicated by setting the value of the dataFormats property to ['application/json].
+
The object MAY contain a schema property, and if present its value MUST be a valid URI string that identifies the protocol the definition pertains to.
+
+
+
+
+
The Protocols Definition object MUST contain a structure property, and its value MUST be a Record Rules object whose keys match the labels defined in the Protocols Definition object. This object is recursive, allowing subsequent record relationships to be defined within. Labeled members of the object are composed as follows:
+
+
The keys of the object MUST be a string that matches one of the types
+
The values representing those keys within the object MUST be an object composed as follows:
+
+
The object MAY contain an $actions property and its value MUST be an array of rule set objects described as follows:
+
+
The object MUST contain a who property and it MUST have one of the following values:
+
+
anyone
+
author
+
recipient
+
+
+
The object MUST contain a can property and it MUST have a value of either read or write
+
The object MAY contain a of property and it MUST have a string value that references one of the types
When processing a ProtocolsConfigure message, a conforming implementation MUST perform the following steps:
+
+
If the message has a lastConfiguration property, ensure the referenced CID value links to a valid previous configuration for the specified protocol + version;
+
If the message:
+2a. Does not contain a protocolDefinition property, process the configuration as if the protocol + version is closed for interaction.
+2b. Does contain a protocolDefinition property, perform any indexing, setup, or optimization processes required to begin enforcing it within the implementation.
The Permissions interface provides a mechanism for external entities to request access
+to various data and functionality provided by a Decentralized Web Node. Permissions employ a
+capabilities-based architecture that allows for DID-based authorization and delegation
+of authorized capabilities to others, if allowed by the owner of a Decentralized Web Node.
PermissionsRequest messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Permissions.
+
The object MUST contain a method property, and its value MUST be the string Request.
+
The object MUST contain a grantedBy property, and its value MUST be the DID URI string of the party that is granting the permission.
+
The object MUST contain a grantedTo property, and its value MUST be the DID URI string of the party that is being granted the permission.
+
The object MAY contain a description property, and its value MUST be a string that the requesting party uses to communicate what the permission is being used for.
+
The object MUST contain a scope property, and its value Must be an object of the following properties:
+
+
The object MUST contain an interface property, and its value MUST be the interface the requesting party wants to invoke.
+
The object MUST contain a method property, and its value MUST be the interface method the requesting party wants to invoke.
+
The object MAY contain a schema property, and its value Must be a URI string that indicates the schema of the associated data.
+
The object MAY contain a protocol property, and its value Must be a URI that denotes the Protocol an object is a part of.
+
The object MAY contain a protocolVersion property, and its value Must be a SemVer string that denotes the version of the Protocol the object is a part of.
+
The object MAY contain a contextId property, and its value Must be the deterministic ID for a contextually linked set of objects.
+
+
+
The object MAY contain a conditions property, and its value Must be an object of the following properties:
+
+
The object MAY contain an attestation property, and if present its value Must be a string representing the signing conditions detailed below. If the property is not present it MUST be evaluated as if it were set to the value optional.
+
+
prohibited - the object MUST NOT be signed.
+
optional - the object MAY be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+
required - the object MUST be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+
+
+
The object MAY contain an encryption property, and if present its value Must be a string representing the encryption conditions detailed below. If the property is not present it MUST be evaluated as if it were set to the value optional.
+
+
optional - the object MAY be encrypted using the key provided by the owner of a Decentralized Web Node in the [RFC7516] JSON Web Encryption (JWE) format.
+
required - the object MUST be encrypted using the key provided by the owner of a Decentralized Web Node in the [RFC7516] JSON Web Encryption (JWE) format.
+
+
+
The object MAY contain a delegation property, and its value Must be a boolean, wherein true indicates the issuing party is allowing the grantee the ability to delegate the capability. A value of false or omission of the property MUST be evaluated as false, and indicates the grantee MUST NOT be allowed to delegate the capability.
+
The object MAY contain a publication property, and its value Must be a boolean, wherein true indicates the issuing party is allowing the grantee the ability to publish data tied to methods that support the public boolean value in their descriptor field sets. Conforming implementations MUST throw an error and fail to grant a permission if this property is present and the method does not support publication.
+
The object MAY contain a sharedAccess property, and its value Must be a boolean, wherein true indicates the requesting
+party wants the ability to use the permission against any object or data that aligns with the capability’s definition, regardless of which
+entity created the object or data. A value of false or omission of the property MUST be evaluated as false, and indicates the
+requesting party only needs the ability to invoke the permission against objects or data it creates.
+
+
+
+
+
The message object MUST contain an authorization property, which MUST be a JSON object as defined by the Message Authorization
+section of this specification, with the requirement that the kid and signatureMUST match the DID of the requesting party.
PermissionsGrant messages are JSON objects containing capabilities granted to parties that curtail the scope of permitted activities an invoker can perform. They are generated either in response to a PermissionsRequest message or optimistically by a user agent without an initiating PermissionsRequest. PermissionsGrant messages include general Message Descriptor properties and the following additional properties:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Permissions.
+
The object MUST contain a method property, and its value MUST be the string Grant.
+
The object MUST contain a permissionGrantId property, and its value MUST be an [RFC4122] UUID Version 4 string representing the reply object.
+
If the granted permission is in response to a PermissionRequest, the object MUST contain a permissionRequestId property, and its value MUST be the [RFC4122] UUID Version 4 string of the PermissionRequest object the permission is being granted in relation to.
+
The object MUST contain a grantedBy property, and its value MUST be the DID URI string of the party that is granting the permission.
+
The object MUST contain a grantedTo property, and its value MUST be the DID URI string of the party that is being granted the permission.
+
If the PermissionsGrant is a delegated permission, the object MUST contain a delegatedFrom property, and its value MUST be an [RFC4122] UUID Version 4 string matching the permissionGrantId of the PermissionsGrant it was delegated from.
+
The object MUST contain a expiry property, and its value MUST be a Unix epoch timestamp that can be used to trigger revocation activities.
+
The object MUST contain a scope property, and its value Must be an object of the following properties:
+
+
The object MUST contain an interface property, and its value MUST be the interface the requesting party wants to invoke.
+
The object MUST contain a method property, and its value MUST be the interface method the requesting party wants to invoke.
+
The object MAY contain a schema property, and its value Must be a URI string that indicates the schema of the associated data.
+
The object MAY contain a protocol property, and its value Must be a URI that denotes the Protocol an object is a part of.
+
The object MAY contain a protocolVersion property, and its value Must be a SemVer string that denotes the version of the Protocol the object is a part of.
+
The object MAY contain a recordId property, and its value Must be a UUID 4 string reference to an object.
+
The object MAY contain a contextId property, and its value Must be the deterministic ID for a contextually linked set of objects.
+
+
+
The object MAY contain a conditions property, and its value Must be an object of the following properties:
+
+
The object MAY contain an attestation property, and if present its value Must be a string representing the signing conditions detailed below. If the property is not present it MUST be evaluated as if it were set to the value optional.
+
+
prohibited - the object MUST NOT be signed.
+
optional - the object MAY be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+
required - the object MUST be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+
+
+
The object MAY contain an encryption property, and if present its value Must be a string representing the encryption conditions detailed below. If the property is not present it MUST be evaluated as if it were set to the value optional.
+
+
optional - the object MAY be encrypted using the key provided by the owner of a Decentralized Web Node in the [RFC7516] JSON Web Encryption (JWE) format.
+
required - the object MUST be encrypted using the key provided by the owner of a Decentralized Web Node in the [RFC7516] JSON Web Encryption (JWE) format.
+
+
+
The object MAY contain a delegation property, and its value Must be a boolean, wherein true indicates the issuing party is allowing the grantee the ability to delegate the capability. A value of false or omission of the property MUST be evaluated as false, and indicates the grantee MUST NOT be allowed to delegate the capability.
+
The object MAY contain a publication property, and its value Must be a boolean, wherein true indicates the issuing party is allowing the grantee the ability to publish data tied to methods that support the public boolean value in their descriptor field sets. Conforming implementations MUST throw an error and fail to grant a permission if this property is present and the method does not support publication.
+
The object MAY contain a sharedAccess property, and its value Must be a boolean, wherein true indicates the requesting
+party wants the ability to use the permission against any object or data that aligns with the capability’s definition, regardless of which
+entity created the object or data. A value of false or omission of the property MUST be evaluated as false, and indicates the
+requesting party only needs the ability to invoke the permission against objects or data it creates.
+
+
+
+
+
The message object MUST contain an authorization property, which MUST be a JSON object as defined by the Message Authorization
+section of this specification, with the requirement that the kid and signatureMUST match the DID of the requesting party.
+
The message MUST contain a data payload, which is a JSON Web Token representation of the granted permission, as defined in the Capability Objects section below.
+
The message MUST contain an encryptionKey property if the data transacted using the permission grant is to be encrypted, per the directives for encryption under the encryption field of the permission’s conditions. If present, the value of the encryptionKey property MUST be a [RFC7516] JSON Web Encryption (JWE) object that contains the encrypted key material required for an authorized party to decrypt the JWE represented by the dataCid value within the descriptor object.
The encryptionKey attribute of a PermissionsGrant is a [RFC7516] JSON Web Encryption (JWE) object that is composed as follows:
+
+
The kid field of the JWE header MUST be a DID URL that identifies the public key type designated for encryption in the DID Document of the PermissionGrant recipient.
+
The ciphertext field MUST be encrypted with the X25519 public key designated for encryption in the DID Document of the PermissionGrant recipient.
+
The data encrypted in the object’s ciphertext field MUST be the JSON Web Key (JWK) object representation of a AES-256 symmetric encryption key generated by the owner of the DWeb Node that will be used to encrypt the data transacted in relation to the associated PermissionGrant.
After generating a PermissionsGrant the user agent (e.g. wallet app with access to authoritative keys for a given DID) MUST commit the granted permission object to the Decentralized Web Node of the DID the grant was issued from. This will ensure that the permission is present when addressed in subsequent interface method invocations.
Once a user agent (e.g. wallet app with access to authoritative keys for a given DID) generates a PermissionsGrant for an entity to permit access to data and functionality, it is the responsibility of the user agent that generated the PermissionsGrant to deliver it to the entity that is the subject. To do this, the user agent MUST generate a Request that includes the PermissionsGrant and send it to the Decentralized Web Node of the subject it has been granted to, in accordance with the Resolution and Request Construction sections of this specification.
Revocation of a permission is the act of closing off any additional or invalid invocations of that permission. The Revoke interface method enables revocation of a permission via direct reference to the permission’s ID.
The Sync interface and its methods allow different Decentralized Web Nodes to communicate and sync on the state of the data they contain, including replication of messages and files.
A conforming implementation MUST be capable of encrypting and decrypting data stored in Decentralized Web Nodes using the following combinations of cryptographic schemes. Each scheme is a pair, wherein the symmetric keys are used to encrypt the data being protected, then subsequently shared with permitted recipients via encryption of the symmetric keys using the asymmetric key of each recipient.
A conforming implementation MUST be capable of encrypting and decrypting data stored in Decentralized Web Nodes using the following combinations of cryptographic schemes. Each scheme is a pair, wherein the symmetric keys are used to encrypt the data being protected, then subsequently shared with permitted recipients via encryption of the symmetric keys using the asymmetric key of each recipient.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/0.0.1-predraft/spec.md b/spec/0.0.1-predraft/spec.md
new file mode 100644
index 0000000..53ae953
--- /dev/null
+++ b/spec/0.0.1-predraft/spec.md
@@ -0,0 +1,1256 @@
+Identity Hub
+==================
+
+**Specification Status:** Draft
+
+**Latest Draft:**
+ [identity.foundation/identity-hub/spec](https://identity.foundation/identity-hub/spec)
+
+
+**Editors:**
+~ [Daniel Buchner](https://www.linkedin.com/in/dbuchner/) (Block)
+~ [Tobias Looker](https://www.linkedin.com/in/tplooker) (Mattr)
+
+**Contributors:**
+~ [Henry Tsai](https://www.linkedin.com/in/henry-tsai-6b884014/) (Microsoft)
+~ [XinAn Xu](https://www.linkedin.com/in/xinan-xu-b868a326/) (Microsoft)
+~ [Moe Jangda](https://www.linkedin.com/in/moejangda/) (Block)
+
+**Participate:**
+~ [GitHub repo](https://github.com/decentralized-identity/identity-hub)
+~ [File a bug](https://github.com/decentralized-identity/identity-hub/issues)
+~ [Commit history](https://github.com/decentralized-identity/identity-hub/commits/master)
+
+------------------------------------
+
+## Abstract
+
+Most digital activities between people, organizations, devices, and other entities
+require the exchange of messages and data. For entities to exchange messages and
+data for credential, app, or service flows, they need an interface through which
+to store, discover, and fetch data related to the flows and experiences they are
+participating in. Identity Hubs are a data storage and message relay mechanism
+entities can use to locate public or private permissioned data related to a given
+Decentralized Identifier (DID). Identity Hubs are a mesh-like datastore construction
+that enable an entity to operate multiple instances that sync to the same state across
+one another, enabling the owning entity to secure, manage, and transact their data
+with others without reliance on location or provider-specific infrastructure,
+interfaces, or routing mechanisms.
+
+## Status of This Document
+
+Identity Hub is a _DRAFT_ specification under development within
+the Decentralized Identity Foundation (DIF). It incorporates requirements and
+learnings from related work of many active industry players into a shared
+specification that meets the collective needs of the community.
+
+The specification will be updated to incorporate feedback, from DIF members and
+the wider community, with a reference implementation being developed within DIF
+that exercises the features and requirements defined here. We encourage reviewers
+to submit [GitHub Issues](https://github.com/decentralized-identity/identity-hub/issues)
+as the means by which to communicate feedback and contributions.
+
+## Terminology
+
+[[def:Identity Hub]]
+~ A decentralized personal and application data storage and message relay node,
+as defined in the DIF Identity Hub specification.
+
+[[def:Hub Instance, Hub Instances]]
+~ An instance of an Identity Hub running on a local device or at a remote location.
+
+[[def:Hub Operator]]
+~ Any entity, including individuals, who runs an Hub Instance on a device or
+infrastructure they control.
+
+[[def:Hub User]]
+~ An entity that stores DID-associated data and transmits messages via a given
+Hub Instance, which may be running on a device in their possession, or on the
+device or infrastructure of a Hub Operator.
+
+[[def:Decentralized Identifiers, Decentralized Identifier, DID]]
+~ Unique ID URI string and PKI metadata document format for describing the
+cryptographic keys and other fundamental PKI values linked to a unique,
+user-controlled, self-sovereign identifier in a target system (e.g., blockchain,
+distributed ledger).
+
+## Topology
+
+
+
+## Protocol Stack
+
+
+
+Identity Hubs are comprised of the following component layers, each of which is defined
+in this specification to ensure multiple Hub implementations can be used together and operate
+as a single logical unit for users.
+
+:----: |
+DID Authentication |
+Access & Authorization |
+Interface Definitions |
+Interface Processing |
+Object Format |
+Object Signing / Encryption |
+File Structure |
+IPFS |
+
+::: todo
+Finalize the component stack list - are these correct? Are we missing any?
+:::
+
+## Service Endpoints
+
+The following DID Document Service Endpoint entries ****MUST**** be present in the DID Document of a target DID for DID-relative URL resolution to properly locate the URI for addressing a DID owner's Hub instances:
+
+```json
+{
+ "id": "did:example:123",
+ "service": [{
+ "id":"#hub",
+ "type": "IdentityHub",
+ "serviceEndpoint": {
+ "instances": ["https://hub.example.com", "https://example.org/hub"]
+ }
+ }]
+}
+```
+
+## Addressing
+
+A user's logical Identity Hub (their collection of Hub Instances) can be addressed in many ways,
+but the mechanisms below ****MUST**** be supported by a compliant Identity Hub implementation:
+
+### DID-Relative URLs
+
+The following DID URL constructions are used to address [[ref: Hub Instances]] found to be associated
+with a given DID, as located via the DID resolution process.
+
+#### Composition
+
+The following process defines how a Identity Hub DID-Relative URL is composed:
+
+1. Let the base URI authority portion of the DID URL string be the target DID being addressed.
+2. Append a `service` parameter to the DID URL string with the value `Identity Hub`.
+3. Assemble an array of the [Message Descriptor](#message-descriptors) objects are desired for encoding in the DID-relative URL
+4. JSON stringify the array of [Message Descriptor](#message-descriptors) objects from Step 3, then Base64Url encode the stringified output.
+5. Append a `queries` parameter to the DID URL string with the value set to the JSON stringified, Base64Url encoded output of Step 4.
+
+**DID-relative URLs are composed of the following segments**
+
+`did:example:123` + `?service=IdentityHub` + `&queries=` + `toBase64Url( JSON.stringify( [{ DESCRIPTOR_1 }, { DESCRIPTOR_N }] ) )`
+
+```json
+did:example:123?service=IdentityHub&queries=W3sgTUVTU0FHRV8xIH0sIHsgTUVTU0FHRV9OIH1d...
+```
+
+#### Resolution
+
+The following process defines how a DID-Relative URL addressing an Identity Hub is resolved:
+
+1. Resolve the DID in the authority portion of the URL in accordance with the [W3C Decentralized Identifier Resolution](https://w3c.github.io/did-core/#resolution) process, which returns the DID Document for the resolved DID.
+2. As indicated by the presence of the `service` parameter, locate the `IdentityHub` entry in the DID Document's [Service Endpoint](https://w3c.github.io/did-core/#services) entries.
+3. Parse the `IdentityHub` Service Endpoint object and select the first URI present in the `serviceEndpoint` objects `instance` array. NOTE: implementers ****SHOULD**** select from the URIs in the `instance` array in index order.
+4. If the URI located in step 3 is not a DID URI, proceed to step 5. If the URI from step 3 is a DID, resolve the DID and follow steps 2 and 3 to select the first URI in the DID's `IdentityHub` Service Endpoint object `instance` array that is not a DID URI. Do not iterate this loop more than once - if a non-DID URI cannot be located after one loop of recursive resolution, terminate resolution and produce an error.
+5. Assuming a non-DID URI was located in steps 2-4, let the located URI be the base URI of the Hub request being constructed.
+
+#### Request Construction
+
+**DID-Relative URL example for passing multiple messages:**
+
+::: note
+For example purposes, the `queries` parameter value below is neither JSON stringified nor Base64Url encoded, but should be when using Identity Hub URLs in practice (see the [DID-relative URL Composition](#composition) instructions above).
+:::
+
+```json
+did:example:123?service=IdentityHub&queries=[{ "method": "CollectionsQuery", "schema": "https://schema.org/SocialMediaPosting" }]
+```
+
+```json
+did:example:123?service=IdentityHub&queries=W3sgTUVTU0FHRV8xIH0sIHsgTUVTU0FHRV9OIH1d...
+```
+
+**Resolve DID to locate the Identity Hub URIs:**
+
+`did:example:123` --> resolve to Identity Hub endpoint(s) --> `https://hub.example.com/`
+
+**Construct the *Request Object*{id=request-object}:**
+
+1. Create a JSON object for the request.
+2. The *Request Object* ****MUST**** include a `id` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string to identify the request.
+3. The *Request Object* ****MUST**** include a `target` property, and its value ****MUST**** be the Decentralized Identifier base URI of the DID-relative URL.
+4. The *Request Object* ****MUST**** include a `messages` property, and its value ****MUST**** be an array composed of [Message](#messages) objects that are generated by parsing the DID-relative URL's `queries` parameter value as a JSON array and performing the following steps for each entry:
+ 1. Construct a [Message](#messages) object.
+ 2. Set the `descriptor` property of the [Message](#messages) object to the entry, ensuring it is a valid [Message Descriptor](#message-descriptors) object.
+ 3. Augment the [Message](#messages) object with any signing and authorization values required, as described in the [Messages](#messages) section.
+ 4. Append the object to the [Request Object](#request-objects)'s `messages` array.
+
+*HTTP POST example:*
+
+```json5
+POST https://hub.example.com/
+
+BODY {
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "target": "did:example:123",
+ "messages": [
+ {
+ "descriptor": {
+ "method": "CollectionsQuery",
+ "schema": "https://schema.org/SocialMediaPosting"
+ }
+ },
+ {...}
+ ]
+}
+```
+
+## Request Objects
+
+Request Objects are JSON object envelopes used to pass messages to Identity Hub instances.
+
+```json
+{ // Request Object
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "target": "did:example:123",
+ "messages": [ // Message Objects
+ {...},
+ {...},
+ {...}
+ ]
+}
+```
+
+Request Objects are composed as follows:
+
+1. The *Request Object* ****MUST**** include a `requestId` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string to identify the request.
+2. The *Request Object* ****MUST**** include a `target` property, and its value ****MUST**** be the Decentralized Identifier base URI of the DID-relative URL.
+3. The *Request Object* ****MUST**** include a `messages` property, and its value ****MUST**** be an array composed of [Message](#messages) objects.
+
+## Messages
+
+All Identity Hub messaging is transacted via Messages JSON objects. These objects contain message execution parameters, authorization material, authorization signatures, and signing/encryption information. For various purposes Messages rely on IPFS CIDs and DAG APIs.
+
+```json
+{ // Request Object
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "target": "did:example:123",
+ "messages": [ // Message Objects
+ {
+ "data": BASE64_STRING,
+ "descriptor": {
+ "method": INTERFACE_METHOD_STRING,
+ "cid": DATA_CID_STRING,
+ "dataFormat": DATA_FORMAT_STRING,
+ },
+ "attestation": {
+ "protected": {
+ "alg": "ES256K",
+ "kid": "did:example:123#key-1"
+ },
+ "payload": CID(descriptor),
+ "signature": Sign(protected + payload)
+ },
+ "authorization": {
+ "protected": {
+ "alg": "ES256K",
+ "kid": "did:example:456#key-2",
+ "capabilities": "...",
+ },
+ "payload": CID(descriptor),
+ "signature": Sign(protected + payload)
+ }
+ },
+ {...}
+ ]
+}
+```
+
+Messages objects ****MUST**** be composed as follows:
+
+In order to enable data replication features for a [[ref: Hub Instance]], all Messages MUST be committed to an IPFS DAG in a tree allocated to the DID of the owner after all subtrees are composed and committed. The top-level of Message objects MUST be committed as a [DAG CBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) encoded object.
+
+- Message objects ****MUST**** contain a `descriptor` property, and its value ****MUST**** be an object, as defined by the [Message Descriptors](#message-descriptors) section of this specification.
+- Message objects ****MAY**** contain a `data` property, and if present its value ****MUST**** be a JSON value of the Message's data.
+- Message objects ****MAY**** contain an `attestation` property, and if present its value ****MUST**** be an object, as defined by the [Signed Data](#signed-data) section of this specification.
+- If a Message object requires signatory and/or permission-evaluated authorization, it ****must**** include an `authorization` property, and its value ****MUST**** be a [[spec:rfc7515]] JSON Web Signature composed as follows:
+ 1. The Message object ****must**** include a `payload` property, and its value ****must**** be the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the [DAG CBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) encoded `descriptor` object, whose composition is defined in the [Message Descriptor](#message-descriptors) section of this specification.
+ 2. The Message object ****MUST**** include a `protected` property, and its value ****must**** be an object composed of the following values:
+ - The object ****MUST**** include an `alg` property, and its value ****MUST**** be the string representing the algorithm used to verify the signature (as defined by the [[spec:rfc7515]] JSON Web Signature specification).
+ - The object ****MUST**** include a `kid` property, and its value ****MUST**** be a [DID URL](https://w3c.github.io/did-core/#example-a-unique-verification-method-in-a-did-document) string identifying the key to be used in verifying the signature.
+ - If the message requires authorization to execute, the Message object ****MUST**** include a `capabilities` property with the required authorization material as its value.
+ 3. The Message object ****MUST**** include a `signature` property, and its value ****must**** be a signature string produced by signing the `payload` value in Step 1, in accordance with the [[spec:rfc7515]] JSON Web Signature specification.
+
+
+### Message Descriptors
+
+The Identity Hub data structure that resides in the `descriptor` property of the [Message](#messages) is comprised of a common JSON structure that contains the following properties regardless of whether the message data is signed/encrypted:
+
+```json
+{ // Request Object
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "target": "did:example:123",
+ "messages": [ // Message Objects
+ {
+ "data": BASE64_STRING,
+ "descriptor": { // Message Descriptor
+ "method": INTERFACE_METHOD_STRING,
+ "cid": DATA_CID_STRING,
+ "dataFormat": DATA_FORMAT_STRING,
+ },
+ "attestation": {...},
+ "authorization": {...}
+ },
+ {...}
+ ]
+}
+```
+
+Message Descriptors are JSON objects that contains the parameters, signatory proof, and other details about the message and any data associated with it. All Message Descriptor objects share the following property options:
+
+- The object ****MUST**** contain a `method` property, and its value ****MUST**** be a string that matches a Hub Interface method.
+- If the [Message](#messages) has data associated with it, passed directly via the `data` property of the [Message](#messages) object or through a channel external to the message object, the `descriptor` object ****MUST**** contain a `cid` property, and its value ****MUST**** be the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the [DAG PB](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-pb.md) encoded data.
+- If the [Message](#messages) has data associated with it, passed directly via the `data` property of the [Message](#messages) object or through a channel external to the message object, the `descriptor` object ****MUST**** contain a `dataFormat` property, and its value ****MUST**** be a string that corresponds with a registered [IANA Media Type](https://www.iana.org/assignments/media-types/media-types.xhtml) data format (the most common being plain JSON, which is indicated by setting the value of the `dataFormat` property to `application/json`), or one of the following format strings pending registration:
+ - `application/vc+jwt` - the data is a JSON Web Token (JWT) [[spec:rfc7519]] formatted variant of a [W3C Verifiable Credential](https://www.w3.org/TR/vc-data-model/#json-web-token).
+ - `application/vc+ldp` - the data is a JSON-LD formatted [W3C Verifiable Credential](https://www.w3.org/TR/vc-data-model).
+
+Individual Interface methods may describe additional properties that the `descriptor` object ****MUST**** or ****MAY**** contain, which are detailed in the [Interfaces](#interfaces) section of the specification.
+
+#### Raw Data
+
+If there is no need or desire to sign or encrypt the content of a message (i.e. public repudiable data), the message `descriptor` object is the only property required in a [Message](#messages) (with any method-specific properties required). An optional `data` property may be passed at the [Message](#messages) level that contains the data associated with the message (when data is desired or required to be present for a given method invocation).
+
+```json
+{ // Message
+ "data": BASE64_STRING,
+ "descriptor": {
+ "objectId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "cid": CID(data),
+ "dateCreated": 123456789,
+ "method": "CollectionsWrite",
+ "schema": "https://schema.org/SocialMediaPosting",
+ "dataFormat": "application/json"
+ }
+}
+```
+
+#### Signed Data
+
+If the object is to be attested by a signer (e.g the Hub owner via signature with their DID key), the object ****MUST**** contain the following additional properties to produce a [[spec:rfc7515]] Flattened JSON Web Signature (JWS) object:
+
+```json
+{ // Message
+ "data": {...},
+ "descriptor": {
+ "objectId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "cid": CID(data),
+ "dateCreated": 123456789,
+ "method": "CollectionsWrite",
+ "schema": "https://schema.org/SocialMediaPosting",
+ "dataFormat": "application/json"
+ },
+ "attestation": {
+ "protected": {
+ "alg": "ES256K",
+ "kid": "did:example:123#key-1"
+ },
+ "payload": CID(descriptor),
+ "signature": Sign(protected + payload)
+ },
+ ...
+}
+```
+
+The message generating party ****MUST**** construct the signed message object as follows:
+
+1. If the [Message](#messages) includes associated data, passed directly via the [Message](#messages) object's `data` property or through a channel external to the [Message](#messages), add a `cid` property to the `descriptor` object and set its value as the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the [DAG PB](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-pb.md) encoded data.
+2. The [Message](#messages) object ****MUST**** contain an `attestation` property, and its value ****MUST**** be a Flattened object representation of a [[spec:rfc7515]] JSON Web Signature composed as follows:
+ 1. The Message object ****must**** include a `payload` property, and its value ****must**** be the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the [DAG CBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) encoded `descriptor` object, whose composition is defined in the [Message Descriptor](#message-descriptors) section of this specification.
+ 2. The Message object ****MUST**** include a `protected` property, and its value ****must**** be an object composed of the following values:
+ - The object ****MUST**** include an `alg` property, and its value ****MUST**** be the string representing the algorithm used to verify the signature (as defined by the [[spec:rfc7515]] JSON Web Signature specification).
+ - The object ****MUST**** include a `kid` property, and its value ****MUST**** be a [DID URL](https://w3c.github.io/did-core/#example-a-unique-verification-method-in-a-did-document) string identifying the key to be used in verifying the signature.
+ 3. The Message object ****MUST**** include a `signature` property, and its value ****must**** be a signature string produced by signing the `protected` and `payload` values, in accordance with the [[spec:rfc7515]] JSON Web Signature specification.
+
+#### Encrypted Data
+
+If the object is to be encrypted (e.g the Hub owner encrypting their data to keep it private), the `descriptor` object ****MUST**** be constructed as follows:
+
+```json
+{ // Message
+ "data": {
+ "protected": ...,
+ "recipients": ...,
+ "ciphertext": ...,
+ "iv": ...,
+ "tag": ...
+ },
+ "descriptor": {
+ "objectId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "cid": CID(data),
+ "dateCreated": 123456789,
+ "method": "CollectionsWrite",
+ "schema": "https://schema.org/SocialMediaPosting",
+ "dataFormat": "application/json",
+ "encryption": "jwe"
+ },
+ ...
+}
+```
+
+The message generating party ****MUST**** construct an encrypted message as follows:
+
+1. The `encryption` property of the `descriptor` object ****MUST**** be set to the string value `JWE`.
+2. Generate an [[spec:rfc7516]] JSON Web Encryption (JWE) object for the data that is to be represented in the message.
+3. Generate a [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) from the JWE of the data produced in Step 1, and set the `cid` property of the `descriptor` object as the stringified representation of the CID.
+
+#### Signed & Encrypted Data
+
+If the object is to be both attributed to a signer and encrypted encrypted, it ****MUST**** be structured as follows:
+
+```json
+{ // Message
+ "data": {
+ "protected": ...,
+ "recipients": ...,
+ "ciphertext": ...,
+ "iv": ...,
+ "tag": ...
+ },
+ "descriptor": {
+ "objectId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "cid": CID(data),
+ "dateCreated": 123456789,
+ "method": "CollectionsWrite",
+ "schema": "https://schema.org/SocialMediaPosting",
+ "dataFormat": "application/json",
+ "encryption": "jwe"
+ },
+ "attestation": {
+ "protected": {
+ "alg": "ES256K",
+ "kid": "did:example:123#key-1"
+ },
+ "payload": CID(descriptor),
+ "signature": Sign(protected + payload)
+ }
+}
+```
+
+The message generating party ****MUST**** construct the signed and encrypted message as follows:
+
+1. Follow the instructions described in the [Encrypted Data](#encrypted-data) section to add the required properties to the `descriptor` and produce a [[spec:rfc7516]] JSON Web Encryption (JWE) object from the associated data.
+2. Follow the instructions described in the [Signed Data](#signed-data) section to add an `attestation` property with a Flattened object representation of a [[spec:rfc7515]] JSON Web Signature as its value.
+
+### Response Objects
+
+Responses from Interface method invocations are JSON objects that ****MUST**** be constructed as follows:
+
+1. The object ****MUST**** include an `requestId` property, and its value ****MUST**** be the [[spec:rfc4122]] UUID Version 4 string from the `requestId` property of the [*Request Object*](#request-object) it is in response to.
+2. The object ****MAY**** have a `status` property if an error is produced from a general request-related issue, and if present its value ****MUST**** be an object composed of the following properties:
+ - The status object ****MUST**** have a `code` property, and its value ****MUST**** be an integer set to the [HTTP Status Code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) appropriate for the status of the response.
+ - The status object ****MAY**** have a `message` property, and if present its value ****MUST**** be a string that describes a terse summary of the status. It is ****recommended**** that the implementer set the message text to the standard title of the HTTP Status Code, when a title/message has already been defined for that code.
+2. The object ****MAY**** have a `replies` property, and if present its value ****MUST**** be an array of *Message Result Objects*{#message-results-objects}, which are constructed as follows:
+ 1. The object ****MUST**** have a `messageId` property, and its value ****MUST**** be the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the associated message in the [*Request Object*](#request-object) from which it was received.
+ 2. The object ****MUST**** have a `status` property, and its value ****MUST**** be an object composed of the following properties:
+ - The status object ****MUST**** have a `code` property, and its value ****MUST**** be an integer set to the [HTTP Status Code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) appropriate for the status of the response.
+ - The status object ****MAY**** have a `message` property, and if present its value ****MUST**** be a string that describes a terse summary of the status. It is ****recommended**** that the implementer set the message text to the standard title of the HTTP Status Code, when a title/message has already been defined for that code.
+ 2. The object ****MAY**** have a `entries` property if the message request was successful. If present, its value ****MUST**** be the resulting message entries returned from the invocation of the corresponding message.
+
+#### Request-Level Status Coding
+
+If any of the scenarios described in this section are encountered during general message processing, the implementation ****must**** include a request-level `status` property, and its value must be an object as defined below.
+
+**Target DID not found**
+
+If the DID targeted by a request object is not found within the Hub instance, the implementation ****MUST**** produce a request-level `status` with the code `404`, and ****SHOULD**** use `Target DID not found within the Identity Hub instance` as the status `text`.
+
+*Response Example:*
+
+::: example Target DID is not found
+```json
+{
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "status": {
+ "code": 404,
+ "text": "Target DID not found within the Identity Hub instance"
+ }
+}
+```
+:::
+
+**General request-level processing errors**
+
+If a general request-level error in processing occurs that is not covered by one of the specific status cases above and prevent the implementation from correctly evaluating the request, the implementation ****MUST**** produce a request-level `status` with the code `500`, and ****SHOULD**** use `The request cannot not be processed` as the status `text`.
+
+*Response Example:*
+
+::: example General request processing error
+```json
+{
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "status": {
+ "code": 500,
+ "text": "The request could not be processed correctly"
+ }
+}
+```
+:::
+
+#### Message-Level Status Coding
+
+If any of the scenarios described in this section are encountered during the processing of an individual message, the implementation ****must**** include a message-level `status` property, and its value must be an object as defined below.
+
+**Message succeeded for query/read-type interface that expects results**
+
+If a message is processed correctly and a set of result `entries` is expected, the implementation ****MUST**** include a message-level `status` object with its `code` property set to `200`, and ****SHOULD**** use `The message was successfully processed` as the status `text`.
+
+::: note
+If no results are found, the `status` remains `200`, and the implementation ****MUST**** return an empty `entries` array.
+:::
+
+*Request Example:*
+
+```json
+{ // Request Object
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "target": "did:example:123",
+ "messages": [ // Message Objects
+ {
+ "descriptor": {
+ "method": "CollectionsQuery",
+ "schema": "https://schema.org/SocialMediaPosting"
+ }
+ },
+ ...
+ ]
+}
+```
+
+*Response Example:*
+
+::: example Example response object
+```json
+{
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "replies": [
+ {
+ "messageId": "bm4vvfvsdfovsj...",
+ "status": { "code": 200, "text": "OK" },
+ "entries": [...]
+ }
+ ]
+}
+```
+:::
+
+**Improperly constructed message**
+
+If a message is malformed or constructed with invalid properties/values, the implementation ****MUST**** include a message-level `status` object with its `code` property set to `400`, and ****SHOULD**** use `The message was malformed or improperly constructed` as the status `text`.
+
+*Request Example:*
+
+```json
+{ // Request Object
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "target": "did:example:123",
+ "messages": [ // Message Objects
+ {
+ "descriptorization": {
+ "methodical": "CollectionsQuery",
+ "schemata": "https://schema.org/SocialMediaPosting"
+ }
+ }
+ ]
+}
+```
+
+*Response Example:*
+
+::: example Example response object
+```json
+{
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "replies": [
+ {
+ "messageId": "bm4vvfvsdfovsj...",
+ "status": { "code": 400, "text": "The message was malformed or improperly constructed" }
+ }
+ ]
+}
+```
+:::
+
+**Message failed authorization requirements**
+
+If a message fails to meet authorization requirements during processing, the implementation ****MUST**** include a message-level `status` object with its `code` property set to `401`, and ****SHOULD**** use `The message failed authorization requirements` as the status `text`.
+
+*Request Example:*
+
+```json
+{ // Request Object
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "target": "did:example:123",
+ "messages": [ // Message Objects
+ { // Message
+ "data": {...},
+ "descriptor": {
+ "objectId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "cid": CID(data),
+ "dateCreated": 123456789,
+ "method": "CollectionsWrite",
+ "schema": "https://schema.org/SocialMediaPosting",
+ "dataFormat": "application/json"
+ }
+
+ ^ `authorization` PROPERTY MISSING
+ }
+ ]
+}
+```
+
+*Response Example:*
+
+::: example Example response object
+```json
+{
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "replies": [
+ {
+ "messageId": "bm2343w4vw45gh...",
+ "status": { "code": 401, "text": "OK" }
+ }
+ ]
+}
+```
+:::
+
+**Interface is not implemented**
+
+If a message attempts to invoke an interface `method` that is not the implementation does not support, the implementation ****MUST**** include a message-level `status` object with its `code` property set to `501`, and ****SHOULD**** use `The interface method is not implemented` as the status `text`.
+
+*Request Example:*
+
+```json
+{ // Request Object
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "target": "did:example:123",
+ "messages": [ // Message Objects
+ { // Message
+ "data": {...},
+ "descriptor": {
+ "objectId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "cid": CID(data),
+ "method": "ThreadsCreate",
+ "schema": "https://schema.org/LikeAction",
+ "dataFormat": "application/json"
+ }
+ }
+ ]
+}
+```
+
+*Response Example:*
+
+::: example Example response object
+```json
+{
+ "requestId": "c5784162-84af-4aab-aff5-f1f8438dfc3d",
+ "replies": [
+ {
+ "messageId": "bm2343w4vw45gh...",
+ "status": { "code": 501, "text": "The interface method is not implemented" }
+ }
+ ]
+}
+```
+:::
+
+## Access & Permissions
+
+::: todo
+Agree on an access/permission scheme (e.g. Object Capabilities) for Hub interactions that require it.
+:::
+
+
+## Sync & Replication
+
+::: todo
+IPFS can provide this to some extent, but do we need anything in addition to what native IPFS provides?
+:::
+
+## Interfaces
+
+### Feature Detection
+
+The Identity Hub specification defines well-recognized Hub configurations to maximize
+interoperability (see Hub Configurations), but implementers may wish to support a custom
+subset of the Interfaces and features. The Feature Detection interface is the means by
+which a Hub expresses support for the Interfaces and features it implements.
+
+#### Data Model
+
+A compliant Identity Hub ****MUST**** produce a Feature Detection object
+defined as follows:
+
+```json
+{
+ "type": "FeatureDetection",
+ "interfaces": { ... }
+}
+```
+
+##### Properties & Values
+
+The following properties and values are defined for the Feature Detection object:
+
+- The object ****MUST**** include an `interfaces` property, and its value ****MUST**** be an object composed as follows:
+ - The object ****MAY**** contain a `collections` property. If the property is not present,
+ it indicates the Hub implementation does not support any methods of the interface. If the
+ property is present, its value ****MUST**** be an object that ****MAY**** include any of the
+ following properties, wherein a boolean `true` value indicates support for the interface
+ method, while a boolean `false` value or omission of the property indicates the interface
+ method is not supported:
+ - `CollectionsQuery`
+ - `CollectionsWrite`
+ - `CollectionsCommit`
+ - `CollectionsDelete`
+ - The object ****MAY**** contain a `actions` property. If the property is not present,
+ it indicates the Hub implementation does not support any methods of the interface. If the
+ property is present, its value ****MUST**** be an object that ****MAY**** include any of the
+ following properties, wherein a boolean `true` value indicates support for the interface
+ method, while a boolean `false` value or omission of the property indicates the interface
+ method is not supported:
+ - `ThreadsQuery`
+ - `ThreadsCreate`
+ - `ThreadsReply`
+ - `ThreadsClose`
+ - `ThreadsDelete`
+ - The object ****MAY**** contain a `permissions` property. If the property is not present,
+ it indicates the Hub implementation does not support any methods of the interface. If the
+ property is present, its value ****MUST**** be an object that ****MAY**** include any of the
+ following properties, wherein a boolean `true` value indicates support for the interface
+ method, while a boolean `false` value or omission of the property indicates the interface
+ method is not supported:
+ - `PermissionsRequest`
+ - `PermissionsGrant`
+ - `PermissionsRevoke`
+- The object ****MAY**** contain a `messaging` property, and its value ****MAY**** be an object composed of the following:
+ - The object ****MAY**** contain a `batching` property, and if present its value ****MUST**** be a boolean indicating whether the Hub Instance handles multiple messages in a single request. The absence of this property ****shall**** indicate that the Hub Instance ****does**** support multiple messages in a single request, thus if an implementer does not support multiple messages in a request, they ****MUST**** include this property and explicitly set its value to `false`.
+
+
+#### Read
+
+All compliant Hubs ****MUST**** respond with a valid Feature Detection object when receiving
+the following request object:
+
+```json
+{ // Message
+ "descriptor": { // Message Descriptor
+ "method": "FeatureDetectionRead"
+ }
+}
+```
+
+### Collections
+
+To maximize decentralized app and service interoperability, the Collections interface of Identity Hubs
+provides a mechanism to store data relative to shared schemas. By storing data in accordance with a
+given schema, which may be well-known in a given vertical or industry, apps and services can leverage
+the same datasets across one another, enabling a cohesive, cross-platform, cross-device, cross-app
+experience for users.
+
+#### Query
+
+`CollectionsQuery` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `CollectionsQuery`.
+ - The object ****MAY**** contain an `objectId` property, and if present its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string intended to identify a logical object the [[ref: Hub Instance]] contains.
+ - The object ****MAY**** contain a `schema` property, and if present its value ****Must**** be a URI string that indicates the schema of the associated data.
+ - The object ****MAY**** contain a `dataFormat` property, and its value ****MUST**** be a string that indicates the format of the data in accordance with its MIME type designation. The most common format is JSON, which is indicated by setting the value of the `dataFormat` property to `application/json`.
+ - The object ****MAY**** contain a `dateSort` field, and if present its value ****MUST**** be one of the following strings:
+ - `createdAscending`: return results in order from the earliest `dateCreated` value to the latest.
+ - `createdDescending`: return results in order from the latest `dateCreated` value to the earliest.
+ - `publishedAscending`: return results in order from the earliest `datePublished` value to the latest.
+ - `publishedDescending`: return results in order from the latest `datePublished` value to the earliest.
+
+Get a single object by its ID reference:
+
+```json
+{ // Message
+ "descriptor": {
+ "method": "CollectionsQuery",
+ "objectId": "b6464162-84af-4aab-aff5-f1f8438dfc1e"
+ }
+}
+```
+
+Get a objects of a given schema type:
+```json
+{ // Message
+ "descriptor": {
+ "method": "CollectionsQuery",
+ "schema": "https://schema.org/MusicPlaylist"
+ }
+}
+```
+
+Get all objects of a given schema type:
+```json
+{ // Message
+ "descriptor": {
+ "method": "CollectionsQuery",
+ "dataFormat": "image/gif"
+ }
+}
+```
+
+#### Write
+
+`CollectionsWrite` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `CollectionsWrite`.
+ - The object ****MUST**** contain an `objectId` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string.
+ - The object ****MAY**** contain a `schema` property, and if present its value ****Must**** be a URI string that indicates the schema of the associated data.
+ - The object ****MUST**** contain a `dateCreated` property, and its value ****MUST**** be an [Unix epoch timestamp](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16) that ****MUST**** be set and interpreted as the time the logical entry was created by the DID owner or another permitted party.
+ - The object ****MAY**** contain a `datePublished` property, and its value ****MUST**** be an [Unix epoch timestamp](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16) that ****MUST**** be set and interpreted as the time the logical entry was published by the DID owner or another permitted party.
+
+```json
+{ // Message
+ "data": {...},
+ "descriptor": { // Message Descriptor
+ "objectId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "cid": CID(data),
+ "dateCreated": 123456789,
+ "method": "CollectionsWrite",
+ "schema": "https://schema.org/SocialMediaPosting",
+ "dataFormat": DATA_FORMAT
+ }
+}
+```
+
+##### Processing Instructions
+
+When processing a `CollectionsWrite` message, Hub instances ****MUST**** perform the following additional steps:
+
+1. If the incoming message has a higher `dateCreated` value than all of the other messages for the logical entry known to the Hub Instance, the message ****MUST**** be designated as the latest state of the logical entry and fully replace all previous messages for the entry.
+2. If the incoming message has a lower `dateCreated` value than the message that represents the current state of the logical entry, the message ****MUST NOT**** be applied to the logical entry and its data ****MAY**** be discarded.
+3. If the incoming message has a `dateCreated` value equal to the message that represents the current state of the logical entry, the incoming message's IPFS CID and the IPFS CID of the message that represents the current state must be lexicographically compared and handled as follows:
+ - If the incoming message has a higher lexicographic value than the message that represents the current state, perform the actions described in Step 1 of this instruction set.
+ - If the incoming message has a lower lexicographic value than the message that represents the current state, perform the actions described in Step 2 of this instruction set.
+
+#### Commit
+
+```json
+{ // Message
+ "data": {...},
+ "descriptor": { // Message Descriptor
+ "objectId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "cid": CID(data),
+ "dateCreated": 123456789,
+ "method": "CollectionsCommit",
+ "schema": "https://schema.org/SocialMediaPosting",
+ "strategy": "merge-patch",
+ "dataFormat": DATA_FORMAT
+ }
+}
+```
+
+`CollectionsCommit` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `CollectionsCommit`.
+ - The object ****MUST**** contain an `objectId` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string.
+ - The object ****MAY**** contain a `schema` property, and if present its value ****Must**** be a URI string that indicates the schema of the associated data.
+ - The object ****MUST**** contain a `dateCreated` property, and its value ****MUST**** be an [Unix epoch timestamp](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16) that ****MUST**** be set and interpreted as the time the logical entry was created by the DID owner or another permitted party.
+ - The object ****MAY**** contain a `datePublished` property, and its value ****MUST**** be an [Unix epoch timestamp](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16) that ****MUST**** be set and interpreted as the time the logical entry was published by the DID owner or another permitted party.
+
+#### Delete
+
+```json
+{ // Message
+ "descriptor": { // Message Descriptor
+ "method": "CollectionsDelete",
+ "objectId": "Qm65765jrn7be64v5q35v6we675br68jr"
+ }
+}
+```
+
+`CollectionsDelete` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `CollectionsDelete`.
+ - The object ****MUST**** contain an `objectId` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string of the object to be deleted.
+
+### Threads
+
+Threads are a linked series of topically associated messages that are intended to result
+in activities performed by entities participating in the message thread.
+
+#### Query
+
+```json
+{ // Message
+ "descriptor": { // Message Descriptor
+ "method": "ThreadsQuery",
+ "schema": "https://schema.org/LikeAction"
+ }
+}
+```
+
+#### Create
+
+```json
+{ // Message
+ "data": {...},
+ "descriptor": { // Message Descriptor
+ "objectId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "method": "ThreadsCreate",
+ "schema": "https://schema.org/LikeAction"
+ }
+}
+```
+
+`ThreadsCreate` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `ThreadsCreate`.
+ - The object ****MUST**** contain an `objectId` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string for the Thread being created.
+ - The object ****MUST**** contain a `schema` property, and its value ****Must**** be a URI string that indicates the schema of the associated data.
+
+#### Reply
+
+```json
+{ // Message
+ "data": {...},
+ "descriptor": { // Message Descriptor
+ "objectId": "65efm7eg-84af-4aab-aff5-f1f8438dfc1e",
+ "method": "ThreadsReply",
+ "schema": "https://fintech.org/BidAcceptance",
+ "root": "b6464162-84af-7gab-aff5-j8f8438dfc1e",
+ "parent": "r7874162-84af-4aab-aff5-f1f8438dfc1e"
+ }
+}
+```
+
+`ThreadsReply` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `ThreadsReply`.
+ - The object ****MUST**** contain an `objectId` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string representing the reply object.
+ - The object ****MUST**** contain a `schema` property, and its value ****Must**** be a URI string that indicates the schema of the associated data.
+ - The object ****MUST**** contain a `root` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string of the initiating Thread message.
+ - The object ****MUST**** contain a `parent` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string of the message in the Thread being replied to.
+
+#### Close
+
+```json
+{ // Message
+ "descriptor": { // Message Descriptor
+ "method": "ThreadsClose",
+ "root": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ }
+}
+```
+
+`ThreadsClose` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `ThreadsClose`.
+ - The object ****MUST**** contain a `root` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string of the initiating Thread message.
+
+#### Delete
+
+```json
+{ // Message
+ "descriptor": { // Message Descriptor
+ "method": "ThreadsDelete",
+ "root": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ }
+}
+```
+
+`ThreadsDelete` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `ThreadsDelete`.
+ - The object ****MUST**** contain a `root` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string of the initiating Thread message.
+
+### Permissions
+
+The Permissions interface provides a mechanism for external entities to request access
+to various data and functionality provided by an Identity Hub. Permissions employ a
+capabilities-based architecture that allows for DID-based authorization and delegation
+of authorized capabilities to others, if allowed by the Identity Hub owner.
+
+#### Request
+
+`PermissionsRequest` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `PermissionsRequest`.
+ - The object ****MUST**** contain an `objectId` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string representing the reply object.
+ - The object ****MUST**** contain a `requester` property, and its value ****MUST**** be the DID URI of the party requesting the permission.
+ - The object ****MAY**** contain a `description` property, and its value ****MUST**** be a string that the requesting party uses to communicate what the permission is being used for.
+ - The object ****MUST**** contain a `ability` property, and its value ****Must**** be an object of the following properties:
+ - The object ****MUST**** contain a `can` property, and its value ****Must**** be an object of the following properties:
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the interface method the requesting party wants to invoke.
+ - The object ****MAY**** contain a `schema` property, and its value ****Must**** be a URI string that indicates the schema of the associated data.
+ - The object ****MAY**** contain a `conditions` property, and its value ****Must**** be an object of the following properties:
+ - The object ****MAY**** contain an `attestation` property, and if present its value ****Must**** be an integer representing the signing conditions detailed below. If the property is not present it ****MUST**** be evaluated as if it were set to a value of `1`.
+ - `0` - the object ****WILL NOT**** be signed.
+ - `1` - the object ****MAY**** be signed using a key linked to the DID of the Hub owner or authoring party (whichever is relevant to the application-level use case), and the signature ****MUST**** be in the [[spec:rfc7515]] JSON Web Signature (JWS) format.
+ - `2` - the object ****MUST**** be signed using a key linked to the DID of the Hub owner or authoring party (whichever is relevant to the application-level use case), and the signature ****MUST**** be in the [[spec:rfc7515]] JSON Web Signature (JWS) format.
+ - The object ****MAY**** contain an `encryption` property, and if present its value ****Must**** be an integer representing the encryption conditions detailed below. If the property is not present it ****MUST**** be evaluated as if it were set to a value of `1`.
+ - `0` - the object ****MUST NOT**** be encrypted.
+ - `1` - the object ****MAY**** be encrypted using the key provided by the owner of the Hub in the [[spec:rfc7516]] JSON Web Encryption (JWE) format.
+ - `2` - the object ****MUST**** be encrypted using the key provided by the owner of the Hub in the [[spec:rfc7516]] JSON Web Encryption (JWE) format.
+ - The object ****MAY**** contain a `delegation` property, and its value ****Must**** be a boolean, wherein `true` indicates the requesting
+ party wants the ability to delegate the capability to other entities, and `false` or the omission of the property indicates no request is being made for delegation ability.
+ - The object ****MAY**** contain a `sharedAccess` property, and its value ****Must**** be a boolean, wherein `true` indicates the requesting
+ party wants the ability to use the permission against any object or data that aligns with the capability's definition, regardless of which
+ entity created the object or data. A value of `false` or omission of the property ****MUST**** be evaluated as false, and indicates the
+ requesting party only needs the ability to invoke the permission against objects or data it creates.
+- The message object ****MUST**** contain an `attestation` property, which ****MUST**** be a JSON object as defined by the [Signed Data](#signed-data)
+ section of this specification, with the requirement that the `kid` and `signature` ****MUST**** match the DID of the requesting party.
+
+```json
+{
+ "descriptor": {
+ "method": "PermissionsRequest",
+ "objectId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "requester": "did:example:bob",
+ "description": "Help you create and edit your music playlists",
+ "ability": {
+ "can": {
+ "method": "CollectionsWrite",
+ "schema": "https://schema.org/MusicPlaylist"
+ },
+ "conditions": {
+ "encryption": 1,
+ "attestation": 0,
+ "delegation": true,
+ "sharedAccess": true
+ }
+ }
+ },
+ "attestation": {
+ "protected": {
+ "alg": "ES256K",
+ "kid": "did:example:bob#key-1"
+ },
+ "payload": CID(descriptor),
+ "signature": Sign(protected + payload)
+ }
+}
+```
+
+#### Grant
+
+`PermissionsGrant` messages are JSON objects that are generated either in response to evaluation of a `PermissionsRequest` message or optimistically by a user agent. `PermissionsGrant` messages include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `PermissionsGrant`.
+ - The object ****MUST**** contain an `objectId` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string representing the reply object.
+ - If the granted permission is in response to a `PermissionRequest`, the object ****MUST**** contain a `grantedFor` property, and its value ****MUST**** be the [[spec:rfc4122]] UUID Version 4 string of the `PermissionRequest` object the permission is being granted in relation to.
+ - The object ****MUST**** contain a `cid` property, and its value ****MUST**** be the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the [DAG PB](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-pb.md) encoded JSON Web Token for the granted permission, as defined in the [Capability Objects](#capability-objects) section below.
+ - The object ****MUST**** contain a `dataFormat` property, and its value ****MUST**** be the string `application/json`, as all granted permissions are represented as JSON Web Tokens generally adherent to the [UCAN](https://github.com/ucan-wg/spec#325-attenuations) capabilities construction.
+- The message object ****MUST**** contain an `attestation` property, which ****MUST**** be a JSON object as defined by the [Signed Data](#signed-data)
+ section of this specification, with the requirement that the `kid` and `signature` ****MUST**** match the DID of the requesting party.
+- The message will contain a `data` payload, which is a JSON Web Token representation of the granted permission as defined in the [Capability Objects](#capability-objects) section below.
+
+```json
+{
+ "descriptor": {
+ "method": "PermissionsGrant",
+ "objectId": "f45wve-5b56v5w-5657b4e-56gqf35v",
+ "grantedFor": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "cid": "bf34455ev6v365eb7r8n9mnbesv5e6be7rn879m",
+ "dataFormat": "application/json"
+ },
+ "data": {
+ "payload": {
+ "iss": "did:example:alice",
+ "aud": "did:example:bob",
+ "exp": 1575606941,
+ "att": [{
+ "can": {
+ "method": "CollectionsWrite",
+ "schema": "https://schema.org/MusicPlaylist",
+ },
+ "conditions": {
+ "encryption": 1,
+ "attestation": 0,
+ "sharedAccess": true
+ }
+ }]
+ },
+ "signature": "fw547v63bo5687wvwbcqp349vwo876uc3q..."
+ }
+}
+```
+
+##### Grantor `PermissionsGrant` Storage
+
+After generating a `PermissionsGrant` the user agent (e.g. wallet app with access to authoritative keys for a given DID) ****MUST**** commit the granted permission object to the Hub of the DID the grant was issued from. This will ensure that the permission is present when addressed in subsequent interface method invocations.
+
+##### Grantee `PermissionsGrant` Delivery
+
+Once a user agent (e.g. wallet app with access to authoritative keys for a given DID) generates a `PermissionsGrant` for an entity to permit access to data and Hub functionality, it is the responsibility of the user agent that generated the `PermissionsGrant` to deliver it to the entity that is the subject. To do this, the user agent ****MUST**** generate a Request that includes the `PermissionsGrant` and send it to the Hub of the subject it has been granted to, in accordance with the [Resolution](#resolution) and [Request Construction](#request-construction) sections of this specification.
+
+#### Revoke
+
+Revocation of a permission is the act of closing off any additional or invalid invocations of that permission. The Revoke interface method enables revocation of a permission via direct reference to the permission's `objectId`. When executing a valid `PermissionsRevoke` invocation an implementation ****MUST**** use the `inclusionProof` value to ensure that only the entries in the Hub indicated by the proof are allowed to be retained in relation to the permission. The process of permission revocation effectively encapsulates all valid invocations of the permission and provides a deterministic means for ensuring no invalid invocations are allowed or persisted across any Hub instance.
+
+```json
+{ // Message
+ "descriptor": { // Message Descriptor
+ "method": "PermissionsRevoke",
+ "objectId": "Qm65765jrn7be64v5q35v6we675br68jr",
+ "inclusionProof": "..."
+ }
+}
+```
+
+#### Capability Objects
+
+Capabilities granted via the Permissions interface are [[spec:rfc7516]] JSON Web Token (JWT) used to secure and attenuate the scope permitted activities.
+The JWTs used in this specification to represent capabilities generally adhere to the JWT variant defined in the
+[UCAN](https://github.com/ucan-wg/spec#325-attenuations) capability-based authorization construction.
+
+Capability objects are JSON Web Tokens that ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `header` property, and its value ****MUST**** be an object composed as follows:
+ - The object ****MUST**** contain an `alg` property, and its value ****MUST**** be a string that notes the algorithm used in signing the JWT.
+ - The object ****MUST**** contain an `typ` property, and its value ****MUST**** be the string `JWT`, indicating the object is a [[spec:rfc7516]] JSON Web Token.
+- The message object ****MUST**** contain a `payload` property, and its value ****MUST**** be an object composed as follows:
+ - The object ****MUST**** contain an `iss` property, and its value ****MUST**** be the DID URI string of the party issuing the capability.
+ - The object ****MUST**** contain an `aud` property, and its value ****MUST**** be the DID URI string of requesting party.
+ - The object ****MAY**** contain an `nbf` property, and its value ****MUST**** be a number representing the UTC Unix Timestamp of when the capability is first active.
+ - The object ****MUST**** contain an `exp` property, and its value ****MUST**** be a number representing the UTC Unix Timestamp of when the capability expires.
+ - The object ****MAY**** contain an `nnc` property, and its value ****MUST**** be a unique string that ****SHOULD**** be cryptographically random.
+ - The object ****MUST**** contain an `att` property, and its value ****MUST**** be an array with exactly one entry that is a JSON object composed as follows, with values selected at the discretion of the granting Hub owner:
+ - The object ****MUST**** contain a `can` property, and its value ****Must**** be an object of the following properties:
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the interface method the granting Hub owner will allow the requesting party wants to invoke.
+ - The object ****MAY**** contain a `schema` property, and its value ****Must**** be a URI string that indicates the schema of the associated data the Hub owner is allowing the grantee to access.
+ - The object ****MAY**** contain a `conditions` property, and its value ****Must**** be an object of the following properties:
+ - The object ****MAY**** contain an `attestation` property, and if present its value ****Must**** be an integer representing the signing conditions detailed below. If the property is not present it ****MUST**** be evaluated as if it were set to a value of `1`.
+ - `0` - the object ****MUST NOT**** be signed.
+ - `1` - the object ****MAY**** be signed using a key linked to the DID of the Hub owner or authoring party (whichever is relevant to the application-level use case), and the signature ****MUST**** be in the [[spec:rfc7515]] JSON Web Signature (JWS) format.
+ - `2` - the object ****MUST**** be signed using a key linked to the DID of the Hub owner or authoring party (whichever is relevant to the application-level use case), and the signature ****MUST**** be in the [[spec:rfc7515]] JSON Web Signature (JWS) format.
+ - The object ****MAY**** contain an `encryption` property, and if present its value ****Must**** be an integer representing the encryption conditions detailed below. If the property is not present it ****MUST**** be evaluated as if it were set to a value of `1`.
+ - `0` - the object ****MUST NOT**** be encrypted.
+ - `1` - the object ****MAY**** be encrypted using the key provided by the owner of the Hub in the [[spec:rfc7516]] JSON Web Encryption (JWE) format.
+ - `2` - the object ****MUST**** be encrypted using the key provided by the owner of the Hub in the [[spec:rfc7516]] JSON Web Encryption (JWE) format.
+ - The object ****MAY**** contain a `delegation` property, and its value ****Must**** be a boolean, wherein `true` indicates the ability to delegate the capability to other entities has been granted, and `false` or the omission of the property indicates the ability to delegate has not been granted.
+ - The object ****MAY**** contain a `sharedAccess` property, and its value ****Must**** be a boolean, wherein `true` indicates the issuing party is allowing the grantee the ability to access any object or data that aligns with the capability's definition, regardless of which entity created the object or data. A value of `false` or omission of the property ****MUST**** be evaluated as false, and indicates the grantee ****MUST NOT**** be allowed to invoke the capability against any object or data they are not the author of.
+ - The object ****MAY**** contain an `prf` property, and its value ****MUST**** be an array of [Capability Objects](#capability-objects) in stringified form that provide proof of delegation for the capability being invoked.
+ - The object ****MAY**** contain an `fct` property, and if present its value ****MUST**** be an array of facts or assertions required for processing the capability that can be verified by the Hub evaluating invocation of the capability.
+
+:::example
+```json
+{
+ "payload": {
+ "iss": "did:example:alice",
+ "aud": "did:example:bob",
+ "nbf": 1529496683,
+ "exp": 1575606941,
+ "nnc": "f5we67hrn8676bwv5cq24WF5WVE6B76F",
+ "att": [{
+ "can": {
+ "method": "CollectionsWrite",
+ "schema": "https://schema.org/MusicPlaylist",
+ },
+ "conditions": {
+ "encryption": 1,
+ "attestation": 0,
+ "sharedAccess": true
+ }
+ }],
+ "prf": ["eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInVhdiI6IjAuMS4wIn0.eyJhdWQiOiJkaWQ6a2V5OnpTdEVacHpTTXRUdDlrMnZzemd2Q3dGNGZMU..."]
+ },
+ "signature": "fw547v63bo5687wvwbcqp349vwo876uc3q..."
+}
+```
+:::
+
+## Commit Strategies
+
+Some interface methods may be bound to, or allow for choice between, the data modification algorithms detailed below. Interfaces methods that are bound to one or more of these strategies will indicate it within their interface definitions under the [Interfaces](#interfaces) section.
+
+### Last-Write Wins
+
+Last-Write Wins is the most basic Commit Strategy that allows for the traditional experience of posting an update to a file that fully replaces the data.
+
+### JSON Merge Patch
+
+::: todo
+Detail JSON Merge Patch as a commit strategy option.
+:::
+
+## Hub Configurations
+
+While it is strongly encouraged to implement the full set of Identity Hub features and Interfaces, not all devices and providers may be capable of doing so. To allow for maximum reach and proliferation in the ecosystem, the following are well-recognized configurations of Identity Hub feature sets that tend to serve different purposes.
+
+### Open Data Publication
+
+This Hub configuration is ideal for implementers who seek to expose intentionally public data via the Identity Hub semantic data discovery Interfaces. This implementation is lightweight does not require the implementer to support any of the authentication, permissioning, or ingest mechanisms that other features and Interfaces do.
+
+```json
+{
+ "type": "FeatureDetection",
+ "interfaces": {
+ "collections": {
+ "CollectionsQuery": true
+ }
+ }
+}
+```
+
+
+## Normative References
+
+[[spec]]
diff --git a/spec/images/topology.svg b/spec/images/topology.svg
new file mode 100644
index 0000000..ebee640
--- /dev/null
+++ b/spec/images/topology.svg
@@ -0,0 +1,594 @@
+
+
+
\ No newline at end of file
diff --git a/spec/index.html b/spec/index.html
new file mode 100644
index 0000000..9ca4ce1
--- /dev/null
+++ b/spec/index.html
@@ -0,0 +1,1591 @@
+
+
+
+
+
+
+
+
+ DIF Decentralized Web Node
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Most digital activities between people, organizations, devices, and other entities
+require the exchange of messages and data. For entities to exchange messages and
+data for credential, app, or service flows, they need an interface through which
+to store, discover, and fetch data related to the flows and experiences they are
+participating in. A Decentralized Web Node (DWN) is a data storage and message relay mechanism
+entities can use to locate public or private permissioned data related to a given
+Decentralized Identifier (DID). Decentralized Web Nodes are a mesh-like datastore construction
+that enable an entity to operate multiple nodes that sync to the same state across
+one another, enabling the owning entity to secure, manage, and transact their data
+with others without reliance on location or provider-specific infrastructure,
+interfaces, or routing mechanisms.
Decentralized Web Node is a DRAFT specification under development within
+the Decentralized Identity Foundation (DIF). It is an active work item of the
+Secure Data Storage Working Group at DIF.
+It incorporates requirements and learnings from related work of many active industry players into a shared
+specification that meets the collective needs of the community.
+
The specification will be updated to incorporate feedback, from DIF members and
+the wider community, with a reference implementation being developed within DIF
+that exercises the features and requirements defined here. We encourage reviewers
+to submit GitHub Issues
+as the means by which to communicate feedback and contributions.
A decentralized personal and application data storage and message relay node,
+as defined in the DIF Decentralized Web Node specification. Users may have multiple
+Nodes that replicate their data between them.
+
Decentralized Identifiers
+
Unique ID URI string and PKI metadata document format for describing the
+cryptographic keys and other fundamental PKI values linked to a unique,
+user-controlled, self-sovereign identifier in a target system (e.g., blockchain,
+distributed ledger).
Decentralized Web Nodes are comprised of the following component layers, each of which is defined
+in this specification to ensure multiple Decentralized Web Node implementations can be used together and operate
+as a single logical unit for users.
All references to this section are out of date and will need to be updated.
+
+
All Decentralized Web Node messaging is transacted via Messages JSON objects. These objects contain message execution parameters, authorization material, authorization signatures, and signing/encryption information. For various purposes Messages rely on IPLD CIDs and DAG APIs.
In order to enable data replication features for a Decentralized Web Node, all Messages MUST be committed to an IPLD DAG in a tree allocated to the DID of the owner after all subtrees are composed and committed. The top-level of Message objects MUST be committed as a DAG CBOR encoded object.
+
+
Message objects MUST contain a recordId property, and its value MUST be the stringified Version 1 CID of the initial entry for the logical record in question, generated by running the the following Record ID Generation Process on the initial record entry:
+
+
Create a JSON object of the following composition:
+
+
The recordId CID generation object MUST contain a descriptorCid property, and its value MUST be the stringified Version 1 CID of the DAG CBOR encoded descriptor object.
Generate a Version 1 CID from the DAG CBOR encoded object and output it in its stringified form.
+
+
+
Message objects MAY contain a data property, and if present its value MUST be a base64Url encoded string of the Message’s data.
+
Message objects MUST contain a descriptor property, and its value MUST be an object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be a string that matches a Decentralized Web Node Interface.
+
The object MUST contain a method property, and its value MUST be a string that matches a Decentralized Web Node Interface method.
+
If the Message has data associated with it, passed directly via the data property of the Message or an external channel (e.g. IPFS fetch), the descriptor object MUST contain a dataCid property, and its value MUST be the stringified Version 1 CID of the DAG PB encoded data.
+
If the Message has data associated with it, passed directly via the data property of the Message object or through a channel external to the message object, the descriptor object MUST contain a dataFormat property, and its value MUST be a string that corresponds with a registered IANA Media Type data format (the most common being plain JSON, which is indicated by setting the value of the dataFormat property to application/json), or one of the following format strings pending registration:
+
Individual Interface methods may describe additional properties that the descriptor object MUST or MAY contain, which are detailed in the Interfaces section of the specification.
Some messages may require authorization material for processing them in accordance with the permissions a Decentralized Web Node owner has specified. If a message requires authorization it MUST include an authorization property with a value that is a [RFC7515] General JSON Web Signature (JWS), constructed as follows:
The JWS MUST include a protected property, and its value must be an object composed of the following values:
+
+
The object MUST include an alg property, and its value MUST be the string representing the algorithm used to verify the signature (as defined by the [RFC7515] JSON Web Signature specification).
+
The object MUST include a kid property, and its value MUST be a DID URL string identifying the key to be used in verifying the signature.
+
+
+
The JWS MUST include a payload property, and its value must be an object composed of the following values:
+
+
The object MUST include a descriptorCid property, and its value MUST be the stringified Version 1 CID of the DAG CBOR encoded descriptor object.
+
The object MAY include a permissionsGrantCid property, and its value MUST be the stringified Version 1 CID of the DAG CBOR encoded Permission Grant being invoked.
+
If attestation of an object is permitted, the payloadMAY include an attestationCid property, and its value MUST be the stringified Version 1 CID of the DAG CBOR encoded attestation string.
If there is no need or desire to sign or encrypt the content of a message (i.e. public repudiable data), the message descriptor object is the only property required in a Message (with any method-specific properties required). An optional data property may be passed at the Message level that contains the data associated with the message (when data is desired or required to be present for a given method invocation).
If the object is to be attested by a signer (e.g the Node owner via signature with their DID key), the object MUST contain the following additional properties to produce a [RFC7515] General JSON Web Signature (JWS):
The message generating party MUST construct the signed message object as follows:
+
+
The Message object MUST contain an attestation property, and its value MUST be a General object representation of a [RFC7515] JSON Web Signature composed as follows:
+
+
The object must include a payload property, and its value must be the stringified Version 1 CID of the DAG CBOR encoded descriptor object, whose composition is defined in the Message Descriptor section of this specification.
+
The object MUST include a protected property, and its value must be an object composed of the following values:
+
+
The object MUST include an alg property, and its value MUST be the string representing the algorithm used to verify the signature (as defined by the [RFC7515] JSON Web Signature specification).
+
The object MUST include a kid property, and its value MUST be a DID URL string identifying the key to be used in verifying the signature.
+
+
+
The object MUST include a signature property, and its value must be a signature string produced by signing the protected and payload values, in accordance with the [RFC7515] JSON Web Signature specification.
The message generating party MUST construct an encrypted message as follows:
+
+
The encryption property of the descriptor object MUST be set to the string label value of a Supported Encryption Format.
+
Generate an encrypted payload from the data conformant with the format specified in the encryption property…
+
Generate a Version 1 CID from the payload produced in Step 2 and let the dataCid property of the descriptor object be the stringified representation of the CID.
The message generating party MUST construct the signed and encrypted message as follows:
+
+
Follow the instructions described in the Encrypted Data section to add the required properties to the descriptor and produce a [RFC7516] JSON Web Encryption (JWE) object from the associated data.
+
Follow the instructions described in the Signed Data section to add an attestation property with a General object representation of a [RFC7515] JSON Web Signature as its value.
Responses from Interface method invocations are JSON objects that MUST be constructed as follows:
+
+
The object MAY have a status property if an error is produced from a general request-related issue, and if present its value MUST be an object composed of the following properties:
+
+
The status object MUST have a code property, and its value MUST be an integer set to the HTTP Status Code appropriate for the status of the response.
+
The status object MAY have a detail property, and if present its value MUST be a string that describes a terse summary of the status. It is recommended that the implementer set the message text to the standard title of the HTTP Status Code, when a title/message has already been defined for that code.
+
+
+
The object MAY have a replies property, and if present its value MUST be an array containing Message Result Objects for all messages that were included in the initiating request object. The Message Result ObjectsMUST be put in the index order that matches the index of each result’s corresponding request message. Message Result Objects are constructed as follows:
+
+
The object MUST have a status property, and its value MUST be an object composed of the following properties:
+
+
The status object MUST have a code property, and its value MUST be an integer set to the HTTP Status Code appropriate for the status of the response.
+
The status object MAY have a detail property, and if present its value MUST be a string that describes a terse summary of the status. It is recommended that the implementer set the message text to the standard title of the HTTP Status Code, when a title/message has already been defined for that code.
+
+
+
The object MAY have a entries property if the message request was successful. If present, its value MUST be the resulting message entries returned from the invocation of the corresponding message.
If any of the scenarios described in this section are encountered during general message processing, the implementation must include a request-level status property, and its value must be an object as defined below.
+
Target DID not found
+
If the DID targeted by a request object is not found within the Decentralized Web Node, the implementation MUST produce a request-level status with the code 404, and SHOULD use Target DID not found within the Decentralized Web Node as the status detail value.
{
+ "status":{
+ "code":404,
+ "detail":"Target DID not found within the Decentralized Web Node"
+ }
+}
+
+
+
General request-level processing errors
+
If a general request-level error in processing occurs that is not covered by one of the specific status cases above and prevent the implementation from correctly evaluating the request, the implementation MUST produce a request-level status with the code 500, and SHOULD use The request cannot not be processed as the status detail value.
If any of the scenarios described in this section are encountered during the processing of an individual message, the implementation must include a message-level status property, and its value must be an object as defined below.
+
Message succeeded for query/read-type interface that expects results
+
If a message is processed correctly and a set of result entries is expected, the implementation MUST include a message-level status object with its code property set to 200, and SHOULD use The message was successfully processed as the status detail value.
If a message is malformed or constructed with invalid properties/values, the implementation MUST include a message-level status object with its code property set to 400, and SHOULD use The message was malformed or improperly constructed as the status detail value.
{
+ "replies":[
+ {
+ "status":{"code":400,"detail":"The message was malformed or improperly constructed"}
+ }
+ ]
+}
+
+
+
Message failed authorization requirements
+
If a message fails to meet authorization requirements during processing, the implementation MUST include a message-level status object with its code property set to 401, and SHOULD use The message failed authorization requirements as the status detail value.
If a message attempts to invoke an interface method that is not the implementation does not support, the implementation MUST include a message-level status object with its code property set to 501, and SHOULD use The interface method is not implemented as the status detail value.
If the DWeb Node instance receiving the request has determined that the rate of resource consumption has exceeded its tolerances and cannot process the request, the instance MUST respond with the following status entry:
To maximize decentralized app and service interoperability, the Records interface of Decentralized Web Nodes
+provides a mechanism to store data relative to shared schemas. By storing data in accordance with a
+given schema, which may be well-known in a given vertical or industry, apps and services can leverage
+the same datasets across one another, enabling a cohesive, cross-platform, cross-device, cross-app
+experience for users.
RecordsRead messages are JSON objects that include general Message Descriptor properties and the following additional properties, which MUST be composed as follows:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Records.
+
The object MUST contain a method property, and its value MUST be the string Read.
+
The object MUST contain a messageTimestamp property, and its value
+MUST be of type string property, and its value MUST be an
+[RFC3339] ISO 8601 timestamp that MUST be set and interpreted
+as the time the RecordsRead record itself was created by the requester.
+
The object MUST contain a recordId property, and its value MUST be the recordId of the logical record with which the entry corresponds.
+
+
+
+
A reference of the json schema can be found in the
+schemas
+directory of the specification.
RecordsQuery messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Records.
+
The object MUST contain a method property, and its value MUST be the string Query.
+
The object MUST contain a messageTimestamp property, and its value
+MUST be of type string property, and its value MUST be an
+[RFC3339] ISO 8601 timestamp that MUST be set and interpreted
+as the time the RecordsQuery message was created by the requester.
+
The object MAY contain a filter property, and if present its value MUST be an object that MAY contain the following properties:
+
+
The object MAY contain a attester property representing the
+creator of the Record(s) did. If present its value MUST be a string in the form of a DID.
+
The object MAY contain a receipient property representing the
+recipient of the Record(s) DID If present its value MUST be a string in the form of a DID.
+
The object MAY contain a schema property, and if present its value Must be a URI string that indicates the schema of the associated data.
+
The object MAY contain a recordId property, and its value MUST be a Computed Record ID.
+
The object MAY contain a parentId property determined from the protocol definition, and if present its
+value MUST be a string that represents the computed record of
+the parent object.
+
The object MAY contain a contextId property, and its value MUST be the deterministic ID for a contextually linked set of objects.
+
The object MAY contain a dateCreated property. If present, it
+MUST include the from and to property described as a string range in the ISO 8601 format.
+
+
The from properties value MUST be of type string property, and its value MUST be an [RFC3339] ISO 8601 timestamp.
+
The to properties value MUST be of type string property, and its value MUST be an [RFC3339] ISO 8601 timestamp.
+
+
+
The object MAY contain a protocol property, and its value MUST be a URI that denotes the Protocol an object is a part of.
+
+
If the object contains a protocol property the object MUST also contain a protocolVersion property, and its value Must be a SemVer string that denotes the version of the Protocol the object is a part of.
+
+
+
The object MAY contain a dataFormat property, and its value MUST be a string that indicates the format of the data in accordance with its MIME type designation. The most common format is JSON, which is indicated by setting the value of the dataFormat property to application/json.
+
The object MAY contain a dateSort field, and if present its value MUST be one of the following strings:
+
+
createdAscending: return results in order from the earliest dateCreated value to the latest.
+
createdDescending: return results in order from the latest dateCreated value to the earliest.
+
publishedAscending: return results in order from the earliest datePublished value to the latest.
+
publishedDescending: return results in order from the latest datePublished value to the earliest.
RecordsWrite messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
+
+
The message object MUST contain a recordId property, and its value MUST be the recordId of the logical record the entry corresponds with. If the message is the initial entry for a new record, the value MUST be set to the resulting string from the Record ID Generation Process.
+
If the message object is attached to a Protocol, and its value MUST be a Computed Context ID. If the message is not attached to a Protocol, it MUST NOT contain a contextId property.
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Records.
+
The object MUST contain a method property, and its value MUST be the string Write.
+
The object MUST include a parentId property if the currently active entry for the record is a RecordsDelete or a CollectionWrite that has a declared a Commit Strategy. The object MUST NOT contain a parentId under any other circumstance. If present, the value of the parentId property MUST be the stringified Version 1 CID of the DAG CBOR encoded descriptor object of the previous RecordsWrite or RecordsDelete entry the message is intending to overwrite.
+
The object MAY contain a protocol property, and its value Must be a URI that denotes the Protocol an object is a part of.
+
+
If the object contains a protocol property the object MUST also contain a protocolVersion property, and its value Must be a SemVer string that denotes the version of the Protocol the object is a part of.
+
+
+
The object MAY contain a schema property, and if present its value Must be a URI string that indicates the schema of the associated data and MUST be treated as an immutable value for the lifetime of the logical record.
+
The object MAY contain a commitStrategy property, and if present its value Must be a string from the table of registered Commit Strategies.
+
The object MAY contain a published property, and if present its value Must be a boolean indicating the record’s publication state. A value of true indicates the record has been published for public queries and consumption without requiring authorization. A value of false or the absence of the property indicates the record MUST NOT be served in response to public queries that lack proper authorization.
+
The object MAY contain an encryption property, and if present its value Must be a string that matches one of the Supported Encryption Formats, indicating the encryption format with which the data is encrypted. The absence of this property indicates the data is not encrypted.
+
The object MUST contain a dateCreated property, and its value MUST be an [RFC3339] ISO 8601 timestamp that MUST be set and interpreted as the time the RecordsWrite was created by the DID owner or another permitted party.
+
The object MAY contain a datePublished property, and its value MUST be an [RFC3339] ISO 8601 timestamp that MUST be set and interpreted as the time the RecordsWrite was published by the DID owner or another permitted party.
RecordsDelete messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Records.
+
The object MUST contain a method property, and its value MUST be the string Delete.
+
The message object MUST contain a recordId property, and its value MUST be the recordId of the logical record the entry corresponds with.
+
The object MUST contain a messageTimestamp property, and its value
+MUST be of type string property, and its value MUST be an [RFC3339] ISO 8601 timestamp that MUST be set and interpreted
+as the time the RecordsDelete record itself was created by the requester.
Retained messages in the Records interface are those that may be stored against the specific record they are associated with. Within the Records interface the RecordsWrite, RecordsCommit, RecordsDelete messages are among the set that may be retained to determine the history and current data state of a record. A conforming implementation MUST perform the following steps to process retained messages:
IF no Initial Entry exists and cease any further processing.
+
+
+
ELSE the message may be an overwriting entry for the record; continue processing.
+
+
+
If a message is not the Initial Entry, its descriptorMUST contain a parentId to determine the entry’s position in the record’s lineage. If a parentId is present proceed with processing, else discard the record and cease processing.
+
Ensure all immutable values from the Initial Entry remained unchanged if present in the inbound message. If any have been mutated, discard the message and cease processing.
+
Retrieve the Latest Checkpoint Entry, which will be either the Initial Entry or the latest RecordsDelete, and compare the parentId value of the inbound message to the Entry ID of the Latest Checkpoint Entry derived from running the Record ID Generation Process on it. If the values match, proceed with processing, if the values do not match discard the message and cease processing.
+
If an existing RecordsWrite entry linked to the Latest Checkpoint Entryis not present and the dateCreated value of the inbound message is greater than the Latest Checkpoint Entry, store the message as the Latest Entry and cease processing, else discard the inbound message and cease processing.
+
If an exiting RecordsWrite entry linked to the Latest Checkpoint Entryis present all of the following conditions must be true:
+
+
The dateCreated value of the inbound message is greater than the existing RecordsWrite, or if the dateCreated values are the same, the Entry ID of the inbound message is greater than the existing entry when the Entry IDs of the two are compared lexicographically.
+
+
+
If all of the following conditions for Step 6 are true, store the inbound message as the Latest Entry and discard the existing RecordsWrite entry that was attached to the Latest Checkpoint Entry.
Ensure the record specified by the inbound message’s recordId exists. If it does not, discard the message and cease processing.
+
Ensure all immutable values from the Initial Entry remained unchanged if present in the inbound message. If any have been mutated, discard the message and cease processing.
+
Fetch the active RecordsDelete entry that exists for the record. If no such entry is present, proceed to the next step. If an active RecordsDelete entry for the record is present, the dateCreated value of the inbound message MUST be greater than the active RecordsDelete entry; if it is not, discard the message and cease processing.
DWeb Nodes are designed to act the substrate upon which a wide variety of decentralized applications and services can be written. With an interface like Records alone, a DWeb Node owner and those they permission can write isolated records, but that alone is not enough to support and facilitate decentralized apps. Protocols introduces a mechanism for declaratively encoding an app or service’s underlying protocol rules, including segmentation of records, relationships between records, data-level requirements, and constraints on how participants interact with a protocol. With the DWeb Node Protocols mechanism, one can model the underpinning protocols for a vast array of use cases in a way that enables interop-by-default between app implementations that ride on top of them.
ProtocolsConfigure messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
Protocol Definition objects are declarative rules within ProtocolConfigure messages that specify the types, relationships, and interactions that are permitted under a given protocol installed in a DWeb Node. Inbound callers who wish to interact with a protocol must adhere to these rules, which DWeb Nodes enforce.
The Protocols Definition object MUST contain a protocol property, and its value Must be a URI that denotes the Protocol the configuration pertains to.
+
The Protocols DefinitionMUST contain a published property, and its value Must be a boolean indicating the ProtocolConfiguration’s publication state.
+
The Protocols Definition object MUST contain a types property, and its value MUST be an object composed as follows:
+
+
The keys of the object MUST be a string that represents the underlying type.
+
The values representing those keys within the object MUST be an object composed as follows:
+
+
The object MUST contain a dataFormats property, and its value MUST be an array of strings that indicate the format of the data in accordance with its MIME type designation. The most common format is JSON, which is indicated by setting the value of the dataFormats property to ['application/json].
+
The object MAY contain a schema property, and if present its value MUST be a valid URI string that identifies the protocol the definition pertains to.
+
+
+
+
+
The Protocols Definition object MUST contain a structure property, and its value MUST be a Record Rules object whose keys match the labels defined in the Protocols Definition object. This object is recursive, allowing subsequent record relationships to be defined within. Labeled members of the object are composed as follows:
+
+
The keys of the object MUST be a string that matches one of the types
+
The values representing those keys within the object MUST be an object composed as follows:
+
+
The object MAY contain an $actions property and its value MUST be an array of rule set objects described as follows:
+
+
The object MUST contain a who property and it MUST have one of the following values:
+
+
anyone
+
author
+
recipient
+
+
+
The object MUST contain a can property and it MUST have a value of either read or write
+
The object MAY contain a of property and it MUST have a string value that references one of the types
When processing a ProtocolsConfigure message, a conforming implementation MUST perform the following steps:
+
+
If the message has a lastConfiguration property, ensure the referenced CID value links to a valid previous configuration for the specified protocol + version;
+
If the message:
+2a. Does not contain a protocolDefinition property, process the configuration as if the protocol + version is closed for interaction.
+2b. Does contain a protocolDefinition property, perform any indexing, setup, or optimization processes required to begin enforcing it within the implementation.
The Permissions interface provides a mechanism for external entities to request access
+to various data and functionality provided by a Decentralized Web Node. Permissions employ a
+capabilities-based architecture that allows for DID-based authorization and delegation
+of authorized capabilities to others, if allowed by the owner of a Decentralized Web Node.
PermissionsRequest messages are JSON objects that include general Message Descriptor properties and the following additional properties, which must be composed as follows:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Permissions.
+
The object MUST contain a method property, and its value MUST be the string Request.
+
The object MUST contain a grantedBy property, and its value MUST be the DID URI string of the party that is granting the permission.
+
The object MUST contain a grantedTo property, and its value MUST be the DID URI string of the party that is being granted the permission.
+
The object MAY contain a description property, and its value MUST be a string that the requesting party uses to communicate what the permission is being used for.
+
The object MUST contain a scope property, and its value Must be an object of the following properties:
+
+
The object MUST contain an interface property, and its value MUST be the interface the requesting party wants to invoke.
+
The object MUST contain a method property, and its value MUST be the interface method the requesting party wants to invoke.
+
The object MAY contain a schema property, and its value Must be a URI string that indicates the schema of the associated data.
+
The object MAY contain a protocol property, and its value Must be a URI that denotes the Protocol an object is a part of.
+
The object MAY contain a protocolVersion property, and its value Must be a SemVer string that denotes the version of the Protocol the object is a part of.
+
The object MAY contain a contextId property, and its value Must be the deterministic ID for a contextually linked set of objects.
+
+
+
The object MAY contain a conditions property, and its value Must be an object of the following properties:
+
+
The object MAY contain an attestation property, and if present its value Must be a string representing the signing conditions detailed below. If the property is not present it MUST be evaluated as if it were set to the value optional.
+
+
prohibited - the object MUST NOT be signed.
+
optional - the object MAY be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+
required - the object MUST be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+
+
+
The object MAY contain an encryption property, and if present its value Must be a string representing the encryption conditions detailed below. If the property is not present it MUST be evaluated as if it were set to the value optional.
+
+
optional - the object MAY be encrypted using the key provided by the owner of a Decentralized Web Node in the [RFC7516] JSON Web Encryption (JWE) format.
+
required - the object MUST be encrypted using the key provided by the owner of a Decentralized Web Node in the [RFC7516] JSON Web Encryption (JWE) format.
+
+
+
The object MAY contain a delegation property, and its value Must be a boolean, wherein true indicates the issuing party is allowing the grantee the ability to delegate the capability. A value of false or omission of the property MUST be evaluated as false, and indicates the grantee MUST NOT be allowed to delegate the capability.
+
The object MAY contain a publication property, and its value Must be a boolean, wherein true indicates the issuing party is allowing the grantee the ability to publish data tied to methods that support the public boolean value in their descriptor field sets. Conforming implementations MUST throw an error and fail to grant a permission if this property is present and the method does not support publication.
+
The object MAY contain a sharedAccess property, and its value Must be a boolean, wherein true indicates the requesting
+party wants the ability to use the permission against any object or data that aligns with the capability’s definition, regardless of which
+entity created the object or data. A value of false or omission of the property MUST be evaluated as false, and indicates the
+requesting party only needs the ability to invoke the permission against objects or data it creates.
+
+
+
+
+
The message object MUST contain an authorization property, which MUST be a JSON object as defined by the Message Authorization
+section of this specification, with the requirement that the kid and signatureMUST match the DID of the requesting party.
PermissionsGrant messages are JSON objects containing capabilities granted to parties that curtail the scope of permitted activities an invoker can perform. They are generated either in response to a PermissionsRequest message or optimistically by a user agent without an initiating PermissionsRequest. PermissionsGrant messages include general Message Descriptor properties and the following additional properties:
+
+
The message object MUST contain a descriptor property, and its value MUST be a JSON object composed as follows:
+
+
The object MUST contain an interface property, and its value MUST be the string Permissions.
+
The object MUST contain a method property, and its value MUST be the string Grant.
+
The object MUST contain a permissionGrantId property, and its value MUST be an [RFC4122] UUID Version 4 string representing the reply object.
+
If the granted permission is in response to a PermissionRequest, the object MUST contain a permissionRequestId property, and its value MUST be the [RFC4122] UUID Version 4 string of the PermissionRequest object the permission is being granted in relation to.
+
The object MUST contain a grantedBy property, and its value MUST be the DID URI string of the party that is granting the permission.
+
The object MUST contain a grantedTo property, and its value MUST be the DID URI string of the party that is being granted the permission.
+
If the PermissionsGrant is a delegated permission, the object MUST contain a delegatedFrom property, and its value MUST be an [RFC4122] UUID Version 4 string matching the permissionGrantId of the PermissionsGrant it was delegated from.
+
The object MUST contain a expiry property, and its value MUST be a Unix epoch timestamp that can be used to trigger revocation activities.
+
The object MUST contain a scope property, and its value Must be an object of the following properties:
+
+
The object MUST contain an interface property, and its value MUST be the interface the requesting party wants to invoke.
+
The object MUST contain a method property, and its value MUST be the interface method the requesting party wants to invoke.
+
The object MAY contain a schema property, and its value Must be a URI string that indicates the schema of the associated data.
+
The object MAY contain a protocol property, and its value Must be a URI that denotes the Protocol an object is a part of.
+
The object MAY contain a protocolVersion property, and its value Must be a SemVer string that denotes the version of the Protocol the object is a part of.
+
The object MAY contain a recordId property, and its value Must be a UUID 4 string reference to an object.
+
The object MAY contain a contextId property, and its value Must be the deterministic ID for a contextually linked set of objects.
+
+
+
The object MAY contain a conditions property, and its value Must be an object of the following properties:
+
+
The object MAY contain an attestation property, and if present its value Must be a string representing the signing conditions detailed below. If the property is not present it MUST be evaluated as if it were set to the value optional.
+
+
prohibited - the object MUST NOT be signed.
+
optional - the object MAY be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+
required - the object MUST be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+
+
+
The object MAY contain an encryption property, and if present its value Must be a string representing the encryption conditions detailed below. If the property is not present it MUST be evaluated as if it were set to the value optional.
+
+
optional - the object MAY be encrypted using the key provided by the owner of a Decentralized Web Node in the [RFC7516] JSON Web Encryption (JWE) format.
+
required - the object MUST be encrypted using the key provided by the owner of a Decentralized Web Node in the [RFC7516] JSON Web Encryption (JWE) format.
+
+
+
The object MAY contain a delegation property, and its value Must be a boolean, wherein true indicates the issuing party is allowing the grantee the ability to delegate the capability. A value of false or omission of the property MUST be evaluated as false, and indicates the grantee MUST NOT be allowed to delegate the capability.
+
The object MAY contain a publication property, and its value Must be a boolean, wherein true indicates the issuing party is allowing the grantee the ability to publish data tied to methods that support the public boolean value in their descriptor field sets. Conforming implementations MUST throw an error and fail to grant a permission if this property is present and the method does not support publication.
+
The object MAY contain a sharedAccess property, and its value Must be a boolean, wherein true indicates the requesting
+party wants the ability to use the permission against any object or data that aligns with the capability’s definition, regardless of which
+entity created the object or data. A value of false or omission of the property MUST be evaluated as false, and indicates the
+requesting party only needs the ability to invoke the permission against objects or data it creates.
+
+
+
+
+
The message object MUST contain an authorization property, which MUST be a JSON object as defined by the Message Authorization
+section of this specification, with the requirement that the kid and signatureMUST match the DID of the requesting party.
+
The message MUST contain a data payload, which is a JSON Web Token representation of the granted permission, as defined in the Capability Objects section below.
+
The message MUST contain an encryptionKey property if the data transacted using the permission grant is to be encrypted, per the directives for encryption under the encryption field of the permission’s conditions. If present, the value of the encryptionKey property MUST be a [RFC7516] JSON Web Encryption (JWE) object that contains the encrypted key material required for an authorized party to decrypt the JWE represented by the dataCid value within the descriptor object.
The encryptionKey attribute of a PermissionsGrant is a [RFC7516] JSON Web Encryption (JWE) object that is composed as follows:
+
+
The kid field of the JWE header MUST be a DID URL that identifies the public key type designated for encryption in the DID Document of the PermissionGrant recipient.
+
The ciphertext field MUST be encrypted with the X25519 public key designated for encryption in the DID Document of the PermissionGrant recipient.
+
The data encrypted in the object’s ciphertext field MUST be the JSON Web Key (JWK) object representation of a AES-256 symmetric encryption key generated by the owner of the DWeb Node that will be used to encrypt the data transacted in relation to the associated PermissionGrant.
After generating a PermissionsGrant the user agent (e.g. wallet app with access to authoritative keys for a given DID) MUST commit the granted permission object to the Decentralized Web Node of the DID the grant was issued from. This will ensure that the permission is present when addressed in subsequent interface method invocations.
Once a user agent (e.g. wallet app with access to authoritative keys for a given DID) generates a PermissionsGrant for an entity to permit access to data and functionality, it is the responsibility of the user agent that generated the PermissionsGrant to deliver it to the entity that is the subject. To do this, the user agent MUST generate a Request that includes the PermissionsGrant and send it to the Decentralized Web Node of the subject it has been granted to, in accordance with the Resolution and Request Construction sections of this specification.
Revocation of a permission is the act of closing off any additional or invalid invocations of that permission. The Revoke interface method enables revocation of a permission via direct reference to the permission’s ID.
The Sync interface and its methods allow different Decentralized Web Nodes to communicate and sync on the state of the data they contain, including replication of messages and files.
A conforming implementation MUST be capable of encrypting and decrypting data stored in Decentralized Web Nodes using the following combinations of cryptographic schemes. Each scheme is a pair, wherein the symmetric keys are used to encrypt the data being protected, then subsequently shared with permitted recipients via encryption of the symmetric keys using the asymmetric key of each recipient.
A conforming implementation MUST be capable of encrypting and decrypting data stored in Decentralized Web Nodes using the following combinations of cryptographic schemes. Each scheme is a pair, wherein the symmetric keys are used to encrypt the data being protected, then subsequently shared with permitted recipients via encryption of the symmetric keys using the asymmetric key of each recipient.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/spec.md b/spec/spec.md
new file mode 100644
index 0000000..7920cab
--- /dev/null
+++ b/spec/spec.md
@@ -0,0 +1,1416 @@
+
+Decentralized Web Node
+==================
+
+**Specification Status:** Draft
+
+**Latest Draft:**
+ [identity.foundation/decentralized-web-node/spec](https://identity.foundation/decentralized-web-node/spec)
+
+
+**Previous Draft:**
+ [0.0.1-predraft](https://identity.foundation/decentralized-web-node/spec/0.0.1-predraft/)
+
+**Companion Guide**
+ [v0.0.1](https://identity.foundation/decentralized-web-node/guide/v0.0.1)
+
+**Chairs**
+
+~ [Andor Kesselman](https://www.linkedin.com/in/andorsk/)
+~ [Liran Cohen](https://www.linkedin.com/in/itsliran/)
+
+**Editors:**
+~ [Daniel Buchner](https://www.linkedin.com/in/dbuchner/) (Block)
+~ [Tobias Looker](https://www.linkedin.com/in/tplooker) (Mattr)
+
+**Contributors:**
+~ [Henry Tsai](https://www.linkedin.com/in/henry-tsai-6b884014/) (Microsoft)
+~ [XinAn Xu](https://www.linkedin.com/in/xinan-xu-b868a326/) (Microsoft)
+~ [Moe Jangda](https://www.linkedin.com/in/moejangda/) (Block)
+
+**Participate:**
+~ [GitHub repo](https://github.com/decentralized-identity/decentralized-web-node)
+~ [File a bug](https://github.com/decentralized-identity/decentralized-web-node/issues)
+~ [Commit history](https://github.com/decentralized-identity/decentralized-web-node/commits/main)
+
+------------------------------------
+
+## Abstract
+
+Most digital activities between people, organizations, devices, and other entities
+require the exchange of messages and data. For entities to exchange messages and
+data for credential, app, or service flows, they need an interface through which
+to store, discover, and fetch data related to the flows and experiences they are
+participating in. A Decentralized Web Node (DWN) is a data storage and message relay mechanism
+entities can use to locate public or private permissioned data related to a given
+Decentralized Identifier (DID). Decentralized Web Nodes are a mesh-like datastore construction
+that enable an entity to operate multiple nodes that sync to the same state across
+one another, enabling the owning entity to secure, manage, and transact their data
+with others without reliance on location or provider-specific infrastructure,
+interfaces, or routing mechanisms.
+
+## Status of This Document
+
+Decentralized Web Node is a _DRAFT_ specification under development within
+the [Decentralized Identity Foundation](https://identity.foundation) (DIF). It is an active work item of the
+[Secure Data Storage Working Group at DIF](https://identity.foundation/working-groups/secure-data-storage.html).
+It incorporates requirements and learnings from related work of many active industry players into a shared
+specification that meets the collective needs of the community.
+
+The specification will be updated to incorporate feedback, from DIF members and
+the wider community, with a reference implementation being developed within DIF
+that exercises the features and requirements defined here. We encourage reviewers
+to submit [GitHub Issues](https://github.com/decentralized-identity/decentralized-web-node/issues)
+as the means by which to communicate feedback and contributions.
+
+## Terminology
+
+[[def:Decentralized Web Node, Decentralized Web Nodes, DWN, Node, Nodes]]
+~ A decentralized personal and application data storage and message relay node,
+as defined in the DIF Decentralized Web Node specification. Users may have multiple
+Nodes that replicate their data between them.
+
+[[def:Decentralized Identifiers, Decentralized Identifier, DID]]
+~ Unique ID URI string and PKI metadata document format for describing the
+cryptographic keys and other fundamental PKI values linked to a unique,
+user-controlled, self-sovereign identifier in a target system (e.g., blockchain,
+distributed ledger).
+
+## Topology
+
+
+
+## Technical Stack
+
+Decentralized Web Nodes are comprised of the following component layers, each of which is defined
+in this specification to ensure multiple Decentralized Web Node implementations can be used together and operate
+as a single logical unit for users.
+
+
+
+:----: |
+DID Authentication |
+Access & Authorization |
+Interface Definitions |
+Interface-Specific Processing |
+Object Format |
+Object Signing / Encryption |
+[IPLD Multiformats](https://multiformats.io/) |
+
+## Service Endpoints
+
+::: warning
+This will be updated
+:::
+
+## Messages
+
+::: warning
+All references to this section are out of date and will need to be updated.
+:::
+
+All Decentralized Web Node messaging is transacted via Messages JSON objects. These objects contain message execution parameters, authorization material, authorization signatures, and signing/encryption information. For various purposes Messages rely on IPLD CIDs and DAG APIs.
+
+```json
+{ // Request Object
+ "messages": [ // Message Objects
+ {
+ "recordId": GENERATED_CID_STRING,
+ "descriptor": {
+ "interface": INTERFACE_STRING,
+ "method": METHOD_STRING,
+ "dataCid": DATA_CID_STRING,
+ "dataFormat": DATA_FORMAT_STRING,
+ }
+ },
+ {...}
+ ]
+}
+```
+
+Messages objects ****MUST**** be composed as follows:
+
+In order to enable data replication features for a [[ref: Decentralized Web Node]], all Messages MUST be committed to an IPLD DAG in a tree allocated to the DID of the owner after all subtrees are composed and committed. The top-level of Message objects MUST be committed as a [DAG CBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) encoded object.
+
+- Message objects ****MUST**** contain a `recordId` property, and its value ****MUST**** be the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the initial entry for the logical record in question, generated by running the the following [_Record ID Generation Process_](#recordid-generation){id=recordid-generation} on the initial record entry:
+ 1. Create a JSON object of the following composition:
+ - The `recordId` CID generation object ****MUST**** contain a `descriptorCid` property, and its value ****MUST**** be the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the [DAG CBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) encoded `descriptor` object.
+ 2. [DAG CBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) encode the composed object.
+ 3. Generate a [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) from the [DAG CBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) encoded object and output it in its stringified form.
+- Message objects ****MAY**** contain a `data` property, and if present its value ****MUST**** be a `base64Url` encoded string of the Message's data.
+- Message objects ****MUST**** contain a `descriptor` property, and its value ****MUST**** be an object composed as follows:
+ - The object ****MUST**** contain an `interface` property, and its value ****MUST**** be a string that matches a Decentralized Web Node Interface.
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be a string that matches a Decentralized Web Node Interface method.
+ - If the [Message](#messages) has data associated with it, passed directly via the `data` property of the [Message](#messages) or an external channel (e.g. IPFS fetch), the `descriptor` object ****MUST**** contain a `dataCid` property, and its value ****MUST**** be the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the [DAG PB](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-pb.md) encoded data.
+ - If the [Message](#messages) has data associated with it, passed directly via the `data` property of the [Message](#messages) object or through a channel external to the message object, the `descriptor` object ****MUST**** contain a `dataFormat` property, and its value ****MUST**** be a string that corresponds with a registered [IANA Media Type](https://www.iana.org/assignments/media-types/media-types.xhtml) data format (the most common being plain JSON, which is indicated by setting the value of the `dataFormat` property to `application/json`), or one of the following format strings pending registration:
+ - `application/vc+jwt` - the data is a JSON Web Token (JWT) [[spec:rfc7519]] formatted variant of a [W3C Verifiable Credential](https://www.w3.org/TR/vc-data-model/#json-web-token).
+ - `application/vc+ldp` - the data is a JSON-LD formatted [W3C Verifiable Credential](https://www.w3.org/TR/vc-data-model).
+
+::: note
+Individual Interface methods may describe additional properties that the `descriptor` object ****MUST**** or ****MAY**** contain, which are detailed in the [Interfaces](#interfaces) section of the specification.
+:::
+
+### Message Authorization
+
+Some messages may require authorization material for processing them in accordance with the permissions a [[ref: Decentralized Web Node]] owner has specified. If a message requires authorization it ****MUST**** include an `authorization` property with a value that is a [[spec:rfc7515]] General JSON Web Signature (JWS), constructed as follows:
+
+```json
+{ // Request Object
+ "messages": [ // Message Objects
+ "data": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
+ "recordId": "b65b7r8n7bewv5w6eb7r8n7t78yj7hbevsv567n8r77bv65b7e6vwvd67b6",
+ "descriptor": {
+ "interface": "Records",
+ "method": "Write",
+ "schema": "https://schema.org/SocialMediaPosting",
+ "dataCid": CID(data),
+ "dateCreated": 123456789,
+ "dataFormat": "application/json"
+ },
+ "attestation": {
+ "payload": "89f5hw458fhw958fq094j9jdq0943j58jfq09j49j40f5qj30jf",
+ "signatures": [{
+ "protected": "4d093qj5h3f9j204fq8h5398hf9j24f5q9h83402048h453q",
+ "signature": "49jq984h97qh3a49j98cq5h38j09jq9853h409jjq09h5q9j4"
+ }]
+ },
+ "authorization": {
+ "payload": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
+ "signatures": [{
+ "protected": "f454w56e57r68jrhe56gw45gw35w65w4f5i54c85j84wh5jj8h5",
+ "signature": "5678nr67e56g45wf546786n9t78r67e45657bern797t8r6e5"
+ }]
+ }
+ },
+ {...}
+ ]
+}
+```
+
+- The JWS ****MUST**** include a `protected` property, and its value ****must**** be an object composed of the following values:
+ - The object ****MUST**** include an `alg` property, and its value ****MUST**** be the string representing the algorithm used to verify the signature (as defined by the [[spec:rfc7515]] JSON Web Signature specification).
+ - The object ****MUST**** include a `kid` property, and its value ****MUST**** be a [DID URL](https://w3c.github.io/did-core/#example-a-unique-verification-method-in-a-did-document) string identifying the key to be used in verifying the signature.
+- The JWS ****MUST**** include a `payload` property, and its value ****must**** be an object composed of the following values:
+ - The object ****MUST**** include a `descriptorCid` property, and its value ****MUST**** be the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the [DAG CBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) encoded `descriptor` object.
+ - The object ****MAY**** include a `permissionsGrantCid` property, and its value ****MUST**** be the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the [DAG CBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) encoded [Permission Grant](#grant) being invoked.
+ - If attestation of an object is permitted, the `payload` ****MAY**** include an `attestationCid` property, and its value ****MUST**** be the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the [DAG CBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) encoded `attestation` string.
+
+### Raw Data
+
+If there is no need or desire to sign or encrypt the content of a message (i.e. public repudiable data), the message `descriptor` object is the only property required in a [Message](#messages) (with any method-specific properties required). An optional `data` property may be passed at the [Message](#messages) level that contains the data associated with the message (when data is desired or required to be present for a given method invocation).
+
+```json
+{ // Message
+ "data": BASE64URL_STRING,
+ "recordId": "b65b7r8n7bewv5w6eb7r8n7t78yj7hbevsv567n8r77bv65b7e6vwvd67b6",
+ "descriptor": {
+ "interface": "Records",
+ "method": "Write",
+ "schema": "https://schema.org/InviteAction",
+ "dataCid": CID(data),
+ "dateCreated": 123456789,
+ "dataFormat": "application/json"
+ }
+}
+```
+
+### Signed Data
+
+If the object is to be attested by a signer (e.g the Node owner via signature with their DID key), the object ****MUST**** contain the following additional properties to produce a [[spec:rfc7515]] General JSON Web Signature (JWS):
+
+```json
+{ // Message
+ "recordId": "b65b7r8n7bewv5w6eb7r8n7t78yj7hbevsv567n8r77bv65b7e6vwvd67b6",
+ "descriptor": {
+ "interface": "Records",
+ "method": "Write",
+ "schema": "https://schema.org/InviteAction",
+ "dataCid": CID(data),
+ "dateCreated": 123456789,
+ "dataFormat": "application/json"
+ },
+ "attestation": {
+ "payload": "89f5hw458fhw958fq094j9jdq0943j58jfq09j49j40f5qj30jf",
+ "signatures": [{
+ "protected": "4d093qj5h3f9j204fq8h5398hf9j24f5q9h83402048h453q",
+ "signature": "49jq984h97qh3a49j98cq5h38j09jq9853h409jjq09h5q9j4"
+ }]
+ }
+ ...
+}
+```
+
+The message generating party ****MUST**** construct the signed message object as follows:
+
+1. The [Message](#messages) object ****MUST**** contain an `attestation` property, and its value ****MUST**** be a General object representation of a [[spec:rfc7515]] JSON Web Signature composed as follows:
+ - The object ****must**** include a `payload` property, and its value ****must**** be the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the [DAG CBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) encoded `descriptor` object, whose composition is defined in the [Message Descriptor](#message-descriptors) section of this specification.
+ - The object ****MUST**** include a `protected` property, and its value ****must**** be an object composed of the following values:
+ - The object ****MUST**** include an `alg` property, and its value ****MUST**** be the string representing the algorithm used to verify the signature (as defined by the [[spec:rfc7515]] JSON Web Signature specification).
+ - The object ****MUST**** include a `kid` property, and its value ****MUST**** be a [DID URL](https://w3c.github.io/did-core/#example-a-unique-verification-method-in-a-did-document) string identifying the key to be used in verifying the signature.
+ - The object ****MUST**** include a `signature` property, and its value ****must**** be a signature string produced by signing the `protected` and `payload` values, in accordance with the [[spec:rfc7515]] JSON Web Signature specification.
+
+### Encrypted Data
+
+If the object is to be encrypted (e.g the Node owner encrypting their data to keep it private), the `descriptor` object ****MUST**** be constructed as follows:
+
+```json
+{ // Message
+ "data": {
+ "protected": ...,
+ "recipients": ...,
+ "ciphertext": ...,
+ "iv": ...,
+ "tag": ...
+ },
+ "recordId": "b65b7r8n7bewv5w6eb7r8n7t78yj7hbevsv567n8r77bv65b7e6vwvd67b6",
+ "descriptor": {
+ "interface": "Records",
+ "method": "Query",
+ "schema": "https://schema.org/SocialMediaPosting"
+ }
+ ...
+}
+```
+
+The message generating party ****MUST**** construct an encrypted message as follows:
+
+1. The `encryption` property of the `descriptor` object ****MUST**** be set to the string label value of a [Supported Encryption Format](#supported-encryption-format).
+2. Generate an encrypted payload from the data conformant with the format specified in the `encryption` property..
+3. Generate a [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) from the payload produced in Step 2 and let the `dataCid` property of the `descriptor` object be the stringified representation of the CID.
+
+### Signed & Encrypted Data
+
+If the object is to be both attributed to a signer and encrypted encrypted, it ****MUST**** be structured as follows:
+
+```json
+{ // Message
+ "data": {
+ "protected": ...,
+ "recipients": ...,
+ "ciphertext": ...,
+ "iv": ...,
+ "tag": ...
+ },
+ "recordId": "b65b7r8n7bewv5w6eb7r8n7t78yj7hbevsv567n8r77bv65b7e6vwvd67b6",
+ "descriptor": {
+ "interface": "Records",
+ "method": "Query",
+ "schema": "https://schema.org/SocialMediaPosting"
+ },
+ "attestation": {
+ "payload": "89f5hw458fhw958fq094j9jdq0943j58jfq09j49j40f5qj30jf",
+ "signatures": [{
+ "protected": "4d093qj5h3f9j204fq8h5398hf9j24f5q9h83402048h453q",
+ "signature": "49jq984h97qh3a49j98cq5h38j09jq9853h409jjq09h5q9j4"
+ }]
+ },
+}
+```
+
+The message generating party ****MUST**** construct the signed and encrypted message as follows:
+
+1. Follow the instructions described in the [Encrypted Data](#encrypted-data) section to add the required properties to the `descriptor` and produce a [[spec:rfc7516]] JSON Web Encryption (JWE) object from the associated data.
+2. Follow the instructions described in the [Signed Data](#signed-data) section to add an `attestation` property with a General object representation of a [[spec:rfc7515]] JSON Web Signature as its value.
+
+### Response Objects
+
+Responses from Interface method invocations are JSON objects that ****MUST**** be constructed as follows:
+
+1. The object ****MAY**** have a `status` property if an error is produced from a general request-related issue, and if present its value ****MUST**** be an object composed of the following properties:
+ - The status object ****MUST**** have a `code` property, and its value ****MUST**** be an integer set to the [HTTP Status Code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) appropriate for the status of the response.
+ - The status object ****MAY**** have a `detail` property, and if present its value ****MUST**** be a string that describes a terse summary of the status. It is ****recommended**** that the implementer set the message text to the standard title of the HTTP Status Code, when a title/message has already been defined for that code.
+2. The object ****MAY**** have a `replies` property, and if present its value ****MUST**** be an array containing *Message Result Objects*{#message-results-objects} for all messages that were included in the initiating request object. The *Message Result Objects* ****MUST**** be put in the index order that matches the index of each result's corresponding request message. *Message Result Objects* are constructed as follows:
+ 1. The object ****MUST**** have a `status` property, and its value ****MUST**** be an object composed of the following properties:
+ - The status object ****MUST**** have a `code` property, and its value ****MUST**** be an integer set to the [HTTP Status Code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) appropriate for the status of the response.
+ - The status object ****MAY**** have a `detail` property, and if present its value ****MUST**** be a string that describes a terse summary of the status. It is ****recommended**** that the implementer set the message text to the standard title of the HTTP Status Code, when a title/message has already been defined for that code.
+ 2. The object ****MAY**** have a `entries` property if the message request was successful. If present, its value ****MUST**** be the resulting message entries returned from the invocation of the corresponding message.
+
+#### Request-Level Status Coding
+
+If any of the scenarios described in this section are encountered during general message processing, the implementation ****must**** include a request-level `status` property, and its value must be an object as defined below.
+
+**Target DID not found**
+
+If the DID targeted by a request object is not found within the Decentralized Web Node, the implementation ****MUST**** produce a request-level `status` with the code `404`, and ****SHOULD**** use `Target DID not found within the Decentralized Web Node` as the status `detail` value.
+
+*Response Example:*
+
+::: example Target DID is not found
+```json
+{
+ "status": {
+ "code": 404,
+ "detail": "Target DID not found within the Decentralized Web Node"
+ }
+}
+```
+:::
+
+**General request-level processing errors**
+
+If a general request-level error in processing occurs that is not covered by one of the specific status cases above and prevent the implementation from correctly evaluating the request, the implementation ****MUST**** produce a request-level `status` with the code `500`, and ****SHOULD**** use `The request cannot not be processed` as the status `detail` value.
+
+*Response Example:*
+
+::: example General request processing error
+```json
+{
+ "status": {
+ "code": 500,
+ "detail": "The request could not be processed correctly"
+ }
+}
+```
+:::
+
+#### Message-Level Status Coding
+
+If any of the scenarios described in this section are encountered during the processing of an individual message, the implementation ****must**** include a message-level `status` property, and its value must be an object as defined below.
+
+**Message succeeded for query/read-type interface that expects results**
+
+If a message is processed correctly and a set of result `entries` is expected, the implementation ****MUST**** include a message-level `status` object with its `code` property set to `200`, and ****SHOULD**** use `The message was successfully processed` as the status `detail` value.
+
+::: note
+If no results are found, the `status` remains `200`, and the implementation ****MUST**** return an empty `entries` array.
+:::
+
+*Request Example:*
+
+```json
+{ // Request Object
+ "messages": [ // Message Objects
+ {
+ "descriptor": {
+ "interface": "Records",
+ "method": "Query",
+ "schema": "https://schema.org/SocialMediaPosting"
+ }
+ },
+ ...
+ ]
+}
+```
+
+*Response Example:*
+
+::: example Example response object
+```json
+{
+ "replies": [
+ {
+ "status": { "code": 200, "detail": "OK" },
+ "entries": [...]
+ }
+ ]
+}
+```
+:::
+
+**Improperly constructed message**
+
+If a message is malformed or constructed with invalid properties/values, the implementation ****MUST**** include a message-level `status` object with its `code` property set to `400`, and ****SHOULD**** use `The message was malformed or improperly constructed` as the status `detail` value.
+
+*Request Example:*
+
+```json
+{ // Request Object
+ "messages": [ // Message Objects
+ {
+ "descriptorization": {
+ "interface": "Records",
+ "method": "Query",
+ "schemata": "https://schema.org/SocialMediaPosting"
+ }
+ }
+ ]
+}
+```
+
+*Response Example:*
+
+::: example Example response object
+```json
+{
+ "replies": [
+ {
+ "status": { "code": 400, "detail": "The message was malformed or improperly constructed" }
+ }
+ ]
+}
+```
+:::
+
+**Message failed authorization requirements**
+
+If a message fails to meet authorization requirements during processing, the implementation ****MUST**** include a message-level `status` object with its `code` property set to `401`, and ****SHOULD**** use `The message failed authorization requirements` as the status `detail` value.
+
+*Request Example:*
+
+```json
+{ // Request Object
+ "messages": [ // Message Objects
+ { // Message
+ "descriptor": {
+ "interface": "Records",
+ "method": "Write",
+ "recordId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "dataCid": CID(data),
+ "dateCreated": 123456789,
+ "schema": "https://schema.org/SocialMediaPosting",
+ "dataFormat": "application/json"
+ }
+
+ ^ `authorization` PROPERTY MISSING
+ }
+ ]
+}
+```
+
+*Response Example:*
+
+::: example Example response object
+```json
+{
+ "replies": [
+ {
+ "status": { "code": 401, "detail": "OK" }
+ }
+ ]
+}
+```
+:::
+
+**Interface is not implemented**
+
+If a message attempts to invoke an interface `method` that is not the implementation does not support, the implementation ****MUST**** include a message-level `status` object with its `code` property set to `501`, and ****SHOULD**** use `The interface method is not implemented` as the status `detail` value.
+
+*Request Example:*
+
+```json
+{ // Request Object
+ "messages": [ // Message Objects
+ { // Message
+ "descriptor": {
+ "interface": "Records",
+ "method": "Write",
+ "recordId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "dataCid": CID(data),
+ "schema": "https://schema.org/LikeAction",
+ "dataFormat": "application/json"
+ }
+ }
+ ]
+}
+```
+
+*Response Example:*
+
+::: example Example response object
+```json
+{
+ "replies": [
+ {
+ "status": {
+ "code": 501,
+ "detail": "The interface method is not implemented"
+ }
+ }
+ ]
+}
+```
+:::
+
+**Resource consumption limit exceeded**
+
+If the DWeb Node instance receiving the request has determined that the rate of resource consumption has exceeded its tolerances and cannot process the request, the instance ****MUST**** respond with the following status entry:
+
+*Response Example:*
+
+::: example Example response object
+```json
+{
+ "replies": [
+ {
+ "status": {
+ "code": 429,
+ "detail": "Resource consumption has exceeded tolerances"
+ }
+ }
+ ]
+}
+```
+:::
+
+## Interfaces
+
+### Records
+
+To maximize decentralized app and service interoperability, the Records interface of Decentralized Web Nodes
+provides a mechanism to store data relative to shared schemas. By storing data in accordance with a
+given schema, which may be well-known in a given vertical or industry, apps and services can leverage
+the same datasets across one another, enabling a cohesive, cross-platform, cross-device, cross-app
+experience for users.
+
+#### `RecordsRead`
+
+`RecordsRead` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****MUST**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain an `interface` property, and its value ****MUST**** be the string `Records`.
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `Read`.
+ - The object ****MUST**** contain a `messageTimestamp` property, and its value
+ ****MUST**** be of type string property, and its value ****MUST**** be an
+ [[spec:rfc3339]] ISO 8601 timestamp that ****MUST**** be set and interpreted
+ as the time the `RecordsRead` record itself was created by the requester.
+ - The object ****MUST**** contain a `recordId` property, and its value ****MUST**** be the `recordId` of the logical record with which the entry corresponds.
+
+A reference of the json schema can be found in the
+[schemas](https://github.com/decentralized-identity/decentralized-web-node/blob/main/schemas/json-schemas/records/records-read.json)
+directory of the specification.
+
+
+
+
+
+
+::: example Records Read - Minimal Example
+
+```json
+{
+ "descriptor": {
+ "recordId": "b65b7r8n7bewv5w6eb7r8n7t78yj7hbevsv567n8r77bv65b7e6vwvd67b6",
+ "messageTimestamp": "2002-10-02T10:00:00-05:00Z",
+ "method": "Read",
+ "interface": "Records"
+ }
+}
+```
+
+
+
+
+::: example Records Read - JSON Schema
+
+```json
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://identity.foundation/dwn/json-schemas/records-read.json",
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "descriptor"
+ ],
+ "properties": {
+ "authorization": {
+ "$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
+ },
+ "descriptor": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "interface",
+ "method",
+ "messageTimestamp",
+ "recordId"
+ ],
+ "properties": {
+ "interface": {
+ "enum": [
+ "Records"
+ ],
+ "type": "string"
+ },
+ "method": {
+ "enum": [
+ "Read"
+ ],
+ "type": "string"
+ },
+ "messageTimestamp": {
+ "type": "string"
+ },
+ "recordId": {
+ "type": "string"
+ }
+ }
+ }
+ }
+}
+```
+
+
+
+#### `RecordsQuery`
+
+`RecordsQuery` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain an `interface` property, and its value ****MUST**** be the string `Records`.
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `Query`.
+ - The object ****MUST**** contain a `messageTimestamp` property, and its value
+ ****MUST**** be of type string property, and its value ****MUST**** be an
+ [[spec:rfc3339]] ISO 8601 timestamp that ****MUST**** be set and interpreted
+ as the time the `RecordsQuery` message was created by the requester.
+ - The object ****MAY**** contain a `filter` property, and if present its value ****MUST**** be an object that ****MAY**** contain the following properties:
+ - The object ****MAY**** contain a `attester` property representing the
+ creator of the `Record(s)` did. If present its value ****MUST**** be a string in the form of a DID.
+ - The object ****MAY**** contain a `receipient` property representing the
+ recipient of the `Record(s)` DID If present its value ****MUST**** be a string in the form of a DID.
+ - The object ****MAY**** contain a `schema` property, and if present its value ****Must**** be a URI string that indicates the schema of the associated data.
+ - The object ****MAY**** contain a `recordId` property, and its value ****MUST**** be a [_Computed Record ID_](#computed-record-ids).
+ - The object ****MAY**** contain a `parentId` property determined from the protocol definition, and if present its
+ value ****MUST**** be a string that represents the computed record of
+ the parent object.
+ - The object ****MAY**** contain a `contextId` property, and its value ****MUST**** be the deterministic ID for a contextually linked set of objects.
+ - The object ****MAY**** contain a `dateCreated` property. If present, it
+ **MUST** include the `from` and `to` property described as a string range in the ISO 8601 format.
+ - The from properties value ****MUST**** be of type string property, and its value ****MUST**** be an [[spec:rfc3339]] ISO 8601 timestamp.
+ - The to properties value ****MUST**** be of type string property, and its value ****MUST**** be an [[spec:rfc3339]] ISO 8601 timestamp.
+ - The object ****MAY**** contain a `protocol` property, and its value ****MUST**** be a URI that denotes the Protocol an object is a part of.
+ - If the object contains a `protocol` property the object ****MUST**** also contain a `protocolVersion` property, and its value ****Must**** be a [SemVer](https://semver.org/) string that denotes the version of the Protocol the object is a part of.
+ - The object ****MAY**** contain a `dataFormat` property, and its value ****MUST**** be a string that indicates the format of the data in accordance with its MIME type designation. The most common format is JSON, which is indicated by setting the value of the `dataFormat` property to `application/json`.
+ - The object ****MAY**** contain a `dateSort` field, and if present its value ****MUST**** be one of the following strings:
+ - `createdAscending`: return results in order from the earliest `dateCreated` value to the latest.
+ - `createdDescending`: return results in order from the latest `dateCreated` value to the earliest.
+ - `publishedAscending`: return results in order from the earliest `datePublished` value to the latest.
+ - `publishedDescending`: return results in order from the latest `datePublished` value to the earliest.
+
+
+
+
+
+
+::: Get a single object by its ID reference:
+
+```json
+{ // Message
+ "descriptor": {
+ "interface": "Records",
+ "method": "Query",
+ "filter": {
+ "recordId": "b6464162-84af-4aab-aff5-f1f8438dfc1e"
+ }
+ }
+}
+```
+
+
+
+
+::: Get an object of a given schema type:
+
+```json
+{ // Message
+ "descriptor": {
+ "interface": "Records",
+ "method": "Query",
+ "filter": {
+ "schema": "https://schema.org/MusicPlaylist"
+ }
+ }
+}
+```
+
+
+
+
+::: Get all objects of a given schema type:
+
+```json
+{ // Message
+ "descriptor": {
+ "interface": "Records",
+ "method": "Query",
+ "dateSort": "createdDescending",
+ "filter": {
+ "dataFormat": "image/gif"
+ }
+ }
+}
+```
+
+
+
+
+
+::: example Records Query - JSON Schema
+
+```json
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://identity.foundation/dwn/json-schemas/records-query.json",
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "descriptor"
+ ],
+ "properties": {
+ "authorization": {
+ "$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
+ },
+ "descriptor": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "interface",
+ "method",
+ "messageTimestamp",
+ "filter"
+ ],
+ "properties": {
+ "interface": {
+ "enum": [
+ "Records"
+ ],
+ "type": "string"
+ },
+ "method": {
+ "enum": [
+ "Query"
+ ],
+ "type": "string"
+ },
+ "messageTimestamp": {
+ "$ref": "https://identity.foundation/dwn/json-schemas/defs.json#/definitions/date-time"
+ },
+ "filter": {
+ "type": "object",
+ "minProperties": 1,
+ "additionalProperties": false,
+ "properties": {
+ "protocol": {
+ "type": "string"
+ },
+ "attester": {
+ "$ref": "https://identity.foundation/dwn/json-schemas/defs.json#/definitions/did"
+ },
+ "recipient": {
+ "$ref": "https://identity.foundation/dwn/json-schemas/defs.json#/definitions/did"
+ },
+ "contextId": {
+ "type": "string"
+ },
+ "schema": {
+ "type": "string"
+ },
+ "recordId": {
+ "type": "string"
+ },
+ "parentId": {
+ "type": "string"
+ },
+ "dataFormat": {
+ "type": "string"
+ },
+ "dateCreated": {
+ "type": "object",
+ "minProperties": 1,
+ "additionalProperties": false,
+ "properties": {
+ "from": {
+ "$ref": "https://identity.foundation/dwn/json-schemas/defs.json#/definitions/date-time"
+ },
+ "to": {
+ "$ref": "https://identity.foundation/dwn/json-schemas/defs.json#/definitions/date-time"
+ }
+ }
+ }
+ }
+ },
+ "dateSort": {
+ "enum": [
+ "createdAscending",
+ "createdDescending",
+ "publishedAscending",
+ "publishedDescending"
+ ],
+ "type": "string"
+ }
+ }
+ }
+ }
+}
+```
+
+
+
+#### `RecordsWrite`
+
+`RecordsWrite` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `recordId` property, and its value ****MUST**** be the `recordId` of the logical record the entry corresponds with. If the message is the initial entry for a new record, the value ****MUST**** be set to the resulting string from the [_Record ID Generation Process_](#recordid-generation).
+- If the message object is attached to a Protocol, and its value ****MUST**** be a [_Computed Context ID_](#computed-context-ids). If the message is not attached to a Protocol, it ****MUST NOT**** contain a `contextId` property.
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain an `interface` property, and its value ****MUST**** be the string `Records`.
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `Write`.
+ - The object ****MUST**** include a `parentId` property if the currently active entry for the record is a `RecordsDelete` or a `CollectionWrite` that has a declared a Commit Strategy. The object ****MUST NOT**** contain a `parentId` under any other circumstance. If present, the value of the `parentId` property ****MUST**** be the stringified [Version 1 CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) of the [DAG CBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) encoded `descriptor` object of the previous `RecordsWrite` or `RecordsDelete` entry the message is intending to overwrite.
+ - The object ****MAY**** contain a `protocol` property, and its value ****Must**** be a URI that denotes the Protocol an object is a part of.
+ - If the object contains a `protocol` property the object ****MUST**** also contain a `protocolVersion` property, and its value ****Must**** be a [SemVer](https://semver.org/) string that denotes the version of the Protocol the object is a part of.
+ - The object ****MAY**** contain a `schema` property, and if present its value ****Must**** be a URI string that indicates the schema of the associated data and ****MUST**** be treated as an immutable value for the lifetime of the logical record.
+ - The object ****MAY**** contain a `commitStrategy` property, and if present its value ****Must**** be a string from the table of registered [Commit Strategies](#commit-strategies).
+ - The object ****MAY**** contain a `published` property, and if present its value ****Must**** be a boolean indicating the record's publication state. A value of `true` indicates the record has been published for public queries and consumption without requiring authorization. A value of `false` or the absence of the property indicates the record ****MUST NOT**** be served in response to public queries that lack proper authorization.
+ - The object ****MAY**** contain an `encryption` property, and if present its value ****Must**** be a string that matches one of the [Supported Encryption Formats](#supported-encryption-format), indicating the encryption format with which the data is encrypted. The absence of this property indicates the data is not encrypted.
+ - The object ****MUST**** contain a `dateCreated` property, and its value ****MUST**** be an [[spec:rfc3339]] ISO 8601 timestamp that ****MUST**** be set and interpreted as the time the `RecordsWrite` was created by the DID owner or another permitted party.
+ - The object ****MAY**** contain a `datePublished` property, and its value ****MUST**** be an [[spec:rfc3339]] ISO 8601 timestamp that ****MUST**** be set and interpreted as the time the `RecordsWrite` was published by the DID owner or another permitted party.
+
+```json
+{ // Message
+ "recordId": "b65b7r8n7bewv5w6eb7r8n7t78yj7hbevsv567n8r77bv65b7e6vwvd67b6",
+ "descriptor": { // Message Descriptor
+ "parentId": CID(PREVIOUS_DESCRIPTOR),
+ "dataCid": CID(data),
+ "dateCreated": 123456789,
+ "published": true,
+ "encryption": "jwe",
+ "interface": "Records",
+ "method": "Write",
+ "schema": "https://schema.org/SocialMediaPosting",
+ "commitStrategy": "json-merge",
+ "dataFormat": DATA_FORMAT
+ }
+}
+```
+#### `RecordsSubscribe`
+
+::: todo
+TODO
+:::
+
+#### `RecordsDelete`
+
+`RecordsDelete` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain an `interface` property, and its value ****MUST**** be the string `Records`.
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `Delete`.
+ - The message object ****MUST**** contain a `recordId` property, and its value ****MUST**** be the `recordId` of the logical record the entry corresponds with.
+ - The object ****MUST**** contain a `messageTimestamp` property, and its value
+ ****MUST**** be of type string property, and its value ****MUST**** be an [[spec:rfc3339]] ISO 8601 timestamp that ****MUST**** be set and interpreted
+ as the time the `RecordsDelete` record itself was created by the requester.
+
+
+
+
+
+
+::: Sample Records Delete
+
+```json
+{
+ "descriptor": {
+ "recordId": "b65b7r8n7bewv5w6eb7r8n7t78yj7hbevsv567n8r77bv65b7e6vwvd67b6",
+ "messageTimestamp": 2002-10-02T10:00:00-05:00Z",
+ "interface": "Records",
+ "method": "Delete"
+ }
+}
+```
+
+
+
+
+::: example Records Delete - JSON Schema
+
+```json
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://identity.foundation/dwn/json-schemas/records-delete.json",
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "authorization",
+ "descriptor"
+ ],
+ "properties": {
+ "authorization": {
+ "$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
+ },
+ "descriptor": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "interface",
+ "method",
+ "messageTimestamp",
+ "recordId"
+ ],
+ "properties": {
+ "interface": {
+ "enum": [
+ "Records"
+ ],
+ "type": "string"
+ },
+ "method": {
+ "enum": [
+ "Delete"
+ ],
+ "type": "string"
+ },
+ "messageTimestamp": {
+ "type": "string"
+ },
+ "recordId": {
+ "type": "string"
+ }
+ }
+ }
+ }
+}
+```
+
+
+
+#### Computed Context IDs
+
+::: todo
+Detail how IDs are computed for record contexts.
+:::
+
+#### Retained Record Processing
+
+Retained messages in the Records interface are those that may be stored against the specific record they are associated with. Within the Records interface the `RecordsWrite`, `RecordsCommit`, `RecordsDelete` messages are among the set that may be retained to determine the history and current data state of a record. A conforming implementation ****MUST**** perform the following steps to process retained messages:
+
+##### If the message is a `RecordsWrite`:
+
+1. Generate the message's [_Entry ID_](#record-entry-id){id=record-entry-id} by performing the [_Record ID Generation Process_](#recordid-generation).
+ - ****IF**** the generated _Entry ID_ matches the `recordId` value of the message --
+ - ****IF**** [_Initial Entry_](#initial-record-entry){id=initial-record-entry} exists for a record, store the entry as the [_Initial Entry_](#initial-record-entry) for the record
+ - ****IF**** no [_Initial Entry_](#initial-record-entry) exists and cease any further processing.
+ - ****ELSE**** the message may be an overwriting entry for the record; continue processing.
+2. If a message is not the [_Initial Entry_](#initial-record-entry), its `descriptor` ****MUST**** contain a `parentId` to determine the entry's position in the record's lineage. If a `parentId` is present proceed with processing, else discard the record and cease processing.
+3. Ensure all immutable values from the [_Initial Entry_](#initial-record-entry) remained unchanged if present in the inbound message. If any have been mutated, discard the message and cease processing.
+4. Retrieve the [_Latest Checkpoint Entry_](#latest-records-checkpoint){id=latest-records-checkpoint}, which will be either the [_Initial Entry_](#initial-record-entry) or the latest `RecordsDelete`, and compare the `parentId` value of the inbound message to the _Entry ID_ of the _Latest Checkpoint Entry_ derived from running the [_Record ID Generation Process_](#recordid-generation) on it. If the values match, proceed with processing, if the values do not match discard the message and cease processing.
+5. If an existing `RecordsWrite` entry linked to the [_Latest Checkpoint Entry_](#latest-records-checkpoint) ****is not**** present and the `dateCreated` value of the inbound message is greater than the [_Latest Checkpoint Entry_](#latest-records-checkpoint), store the message as the _Latest Entry_ and cease processing, else discard the inbound message and cease processing.
+6. If an exiting `RecordsWrite` entry linked to the [_Latest Checkpoint Entry_](#latest-records-checkpoint) ****is**** present all of the following conditions ****must**** be true:
+ - The `dateCreated` value of the inbound message is greater than the existing `RecordsWrite`, or if the `dateCreated` values are the same, the [_Entry ID_](#record-entry-id) of the inbound message is greater than the existing entry when the [_Entry IDs_](#record-entry-id) of the two are compared lexicographically.
+7. If all of the following conditions for Step 6 are true, store the inbound message as the _Latest Entry_ and discard the existing `RecordsWrite` entry that was attached to the [_Latest Checkpoint Entry_](#latest-records-checkpoint).
+
+##### If the message is a `RecordsDelete`:
+
+1. Ensure the record specified by the inbound message's `recordId` exists. If it does not, discard the message and cease processing.
+2. Ensure all immutable values from the [_Initial Entry_](#initial-record-entry) remained unchanged if present in the inbound message. If any have been mutated, discard the message and cease processing.
+3. Fetch the active `RecordsDelete` entry that exists for the record. If no such entry is present, proceed to the next step. If an active `RecordsDelete` entry for the record is present, the `dateCreated` value of the inbound message ****MUST**** be greater than the active `RecordsDelete` entry; if it is not, discard the message and cease processing.
+4. Store the message as the [_Latest Checkpoint Entry_](#latest-records-checkpoint), delete all messages back to the [_Initial Entry_](#initial-record-entry), including their data, and cease processing.
+
+### Protocols
+
+DWeb Nodes are designed to act the substrate upon which a wide variety of decentralized applications and services can be written. With an interface like [Records](#records) alone, a DWeb Node owner and those they permission can write isolated records, but that alone is not enough to support and facilitate decentralized apps. Protocols introduces a mechanism for declaratively encoding an app or service's underlying protocol rules, including segmentation of records, relationships between records, data-level requirements, and constraints on how participants interact with a protocol. With the DWeb Node Protocols mechanism, one can model the underpinning protocols for a vast array of use cases in a way that enables interop-by-default between app implementations that ride on top of them.
+
+#### `ProtocolsConfigure`
+
+`ProtocolsConfigure` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+```json
+{
+ "interface": "Protocols", // required
+ "method": "Configure", // required
+ "protocolVersion": "1.0.0", // required
+ "definition": { PROTOCOL_DEFINITION_OBJ }, // optional
+}
+```
+
+- The message object ****MUST**** contain a `recordId` property, and its value ****MUST**** be the `recordId` of the logical record the entry corresponds with.
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain an `interface` property, and its value ****MUST**** be the string `Protocols`.
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `Configure`.
+ - The object ****MUST**** contain a `definition` property, and its value ****Must**** be a [Protocol Definition](#protocol-definitions) object.
+
+#### Protocol Definitions
+
+Protocol Definition objects are declarative rules within `ProtocolConfigure` messages that specify the types, relationships, and interactions that are permitted under a given protocol installed in a DWeb Node. Inbound callers who wish to interact with a protocol must adhere to these rules, which DWeb Nodes enforce.
+
+```json
+{
+ "interface": "Protocols",
+ "method": "Configure",
+ "definition": {
+ "protocol": "https://decentralized-social-example.org/protocol/",
+ "published": true,
+ "types": {
+ "post": {
+ "schema": "https://decentralized-social-example.org/schemas/post",
+ "dataFormat": ["application/json"],
+ },
+ "reply": {
+ "schema": "https://decentralized-social-example.org/schemas/reply",
+ "dataFormat": ["application/json"],
+ },
+ "image": {
+ "dataFormat": ["image/jpeg", "image/png", "image/gif"],
+ }
+ },
+ "structure": {
+ "post": {
+ "$actions": [{
+ "who": "anyone",
+ "can": "read",
+ }],
+ "reply": {
+ "$actions":[{
+ "who": "anyone",
+ "can": "write",
+ }],
+ "image": {
+ "$actions": [{
+ "who": "anyone",
+ "can": "read",
+ },{
+ "who": "author",
+ "of": "reply",
+ "can": "write",
+ }]
+ }
+ },
+ "image": {
+ "$actions":[{
+ "who": "anyone",
+ "can": "read",
+ }, {
+ "who": "author",
+ "of": "post",
+ "can": "write",
+ }]
+ }
+ }
+ }
+ }
+}
+```
+- The _Protocols Definition_ object ****MUST**** contain a `protocol` property, and its value ****Must**** be a URI that denotes the Protocol the configuration pertains to.
+- The _Protocols Definition_ ****MUST**** contain a `published` property, and its value ****Must**** be a boolean indicating the `ProtocolConfiguration`'s publication state.
+- The _Protocols Definition_ object ****MUST**** contain a `types` property, and its value ****MUST**** be an object composed as follows:
+ - The keys of the object ****MUST**** be a string that represents the underlying type.
+ - The values representing those keys within the object ****MUST**** be an object composed as follows:
+ - The object ****MUST**** contain a `dataFormats` property, and its value ****MUST**** be an array of strings that indicate the format of the data in accordance with its MIME type designation. The most common format is JSON, which is indicated by setting the value of the `dataFormats` property to `['application/json]`.
+ - The object ****MAY**** contain a `schema` property, and if present its value ****MUST**** be a valid URI string that identifies the protocol the definition pertains to.
+- The _Protocols Definition_ object ****MUST**** contain a `structure` property, and its value ****MUST**** be a _Record Rules_ object whose keys match the labels defined in the _Protocols Definition_ object. This object is recursive, allowing subsequent record relationships to be defined within. Labeled members of the object are composed as follows:
+ - The keys of the object ****MUST**** be a string that matches one of the `types`
+ - The values representing those keys within the object ****MUST**** be an object composed as follows:
+ - The object ****MAY**** contain an `$actions` property and its value ****MUST**** be an array of rule set objects described as follows:
+ - The object ****MUST**** contain a `who` property and it ****MUST**** have one of the following values:
+ - `anyone`
+ - `author`
+ - `recipient`
+ - The object ****MUST**** contain a `can` property and it ****MUST**** have a value of either `read` or `write`
+ - The object ****MAY**** contain a `of` property and it ****MUST**** have a string value that references one of the `types`
+
+
+::: todo
+ADD PROTOCOL DEFINITION SPEC TEXT
+:::
+
+##### Processing Instructions
+
+When processing a `ProtocolsConfigure` message, a conforming implementation ****MUST**** perform the following steps:
+
+1. If the message has a `lastConfiguration` property, ensure the referenced CID value links to a valid previous configuration for the specified protocol + version;
+2. If the message:
+ 2a. Does not contain a `protocolDefinition` property, process the configuration as if the protocol + version is closed for interaction.
+ 2b. Does contain a `protocolDefinition` property, perform any indexing, setup, or optimization processes required to begin enforcing it within the implementation.
+3. Store the configuration.
+
+#### `ProtocolsQuery`
+
+The `ProtocolsQuery` interface method allows an outside entity to query for any active protocols the owner has an active configuration for.
+
+```json
+{
+ "interface": "Protocols",
+ "method": "Query",
+ "filter": {
+ "protocol": "identity.foundation/protocols/credential-issuance",
+ "versions": ["1.0.0", "2.0.0"]
+ }
+}
+```
+
+
+### Permissions
+
+The Permissions interface provides a mechanism for external entities to request access
+to various data and functionality provided by a Decentralized Web Node. Permissions employ a
+capabilities-based architecture that allows for DID-based authorization and delegation
+of authorized capabilities to others, if allowed by the owner of a Decentralized Web Node.
+
+#### `PermissionsRequest`
+
+`PermissionsRequest` messages are JSON objects that include general [Message Descriptor](#message-descriptors) properties and the following additional properties, which ****must**** be composed as follows:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain an `interface` property, and its value ****MUST**** be the string `Permissions`.
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `Request`.
+ - The object ****MUST**** contain a `grantedBy` property, and its value ****MUST**** be the DID URI string of the party that is granting the permission.
+ - The object ****MUST**** contain a `grantedTo` property, and its value ****MUST**** be the DID URI string of the party that is being granted the permission.
+ - The object ****MAY**** contain a `description` property, and its value ****MUST**** be a string that the requesting party uses to communicate what the permission is being used for.
+ - The object ****MUST**** contain a `scope` property, and its value ****Must**** be an object of the following properties:
+ - The object ****MUST**** contain an `interface` property, and its value ****MUST**** be the interface the requesting party wants to invoke.
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the interface method the requesting party wants to invoke.
+ - The object ****MAY**** contain a `schema` property, and its value ****Must**** be a URI string that indicates the schema of the associated data.
+ - The object ****MAY**** contain a `protocol` property, and its value ****Must**** be a URI that denotes the Protocol an object is a part of.
+ - The object ****MAY**** contain a `protocolVersion` property, and its value ****Must**** be a [SemVer](https://semver.org/) string that denotes the version of the Protocol the object is a part of.
+ - The object ****MAY**** contain a `contextId` property, and its value ****Must**** be the deterministic ID for a contextually linked set of objects.
+ - The object ****MAY**** contain a [`conditions` property](#permission-conditions){ id=permission-conditions }, and its value ****Must**** be an object of the following properties:
+ - The object ****MAY**** contain an `attestation` property, and if present its value ****Must**** be a `string` representing the signing conditions detailed below. If the property is not present it ****MUST**** be evaluated as if it were set to the value `optional`.
+ - `prohibited` - the object ****MUST NOT**** be signed.
+ - `optional` - the object ****MAY**** be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+ - `required` - the object ****MUST**** be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+ - The object ****MAY**** contain an `encryption` property, and if present its value ****Must**** be a `string` representing the encryption conditions detailed below. If the property is not present it ****MUST**** be evaluated as if it were set to the value `optional`.
+ - `optional` - the object ****MAY**** be encrypted using the key provided by the owner of a Decentralized Web Node in the [[spec:rfc7516]] JSON Web Encryption (JWE) format.
+ - `required` - the object ****MUST**** be encrypted using the key provided by the owner of a Decentralized Web Node in the [[spec:rfc7516]] JSON Web Encryption (JWE) format.
+ - The object ****MAY**** contain a `delegation` property, and its value ****Must**** be a boolean, wherein `true` indicates the issuing party is allowing the grantee the ability to delegate the capability. A value of `false` or omission of the property ****MUST**** be evaluated as false, and indicates the grantee ****MUST NOT**** be allowed to delegate the capability.
+ - The object ****MAY**** contain a `publication` property, and its value ****Must**** be a boolean, wherein `true` indicates the issuing party is allowing the grantee the ability to publish data tied to methods that support the `public` boolean value in their descriptor field sets. Conforming implementations ****MUST**** throw an error and fail to grant a permission if this property is present and the `method` does not support publication.
+ - The object ****MAY**** contain a `sharedAccess` property, and its value ****Must**** be a boolean, wherein `true` indicates the requesting
+ party wants the ability to use the permission against any object or data that aligns with the capability's definition, regardless of which
+ entity created the object or data. A value of `false` or omission of the property ****MUST**** be evaluated as false, and indicates the
+ requesting party only needs the ability to invoke the permission against objects or data it creates.
+- The message object ****MUST**** contain an `authorization` property, which ****MUST**** be a JSON object as defined by the [Message Authorization](#message-authorization)
+ section of this specification, with the requirement that the `kid` and `signature` ****MUST**** match the DID of the requesting party.
+
+```json
+{
+ "descriptor": {
+ "interface": "Permissions",
+ "method": "Request",
+ "permissionRequestId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "grantedBy": "did:example:alice",
+ "grantedTo": "did:example:bob",
+ "description": "Help you create and edit your music playlists",
+ "scope": {
+ "interface": "Records",
+ "method": "Write",
+ "schema": "https://schema.org/MusicPlaylist"
+ },
+ "conditions": {
+ "delegation": true,
+ "publication": true,
+ "sharedAccess": true,
+ "encryption": "optional",
+ "attestation": "prohibited"
+ }
+ },
+ "authorization": {
+ "payload": "89f5hw458fhw958fq094j9jdq0943j58jfq09j49j40f5qj30jf",
+ "signatures": [{
+ "protected": "4d093qj5h3f9j204fq8h5398hf9j24f5q9h83402048h453q",
+ "signature": "49jq984h97qh3a49j98cq5h38j09jq9853h409jjq09h5q9j4"
+ }]
+ }
+}
+```
+
+#### `PermissionsGrant`
+
+`PermissionsGrant` messages are JSON objects containing capabilities granted to parties that curtail the scope of permitted activities an invoker can perform. They are generated either in response to a `PermissionsRequest` message or optimistically by a user agent without an initiating `PermissionsRequest`. `PermissionsGrant` messages include general [Message Descriptor](#message-descriptors) properties and the following additional properties:
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain an `interface` property, and its value ****MUST**** be the string `Permissions`.
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `Grant`.
+ - The object ****MUST**** contain a `permissionGrantId` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string representing the reply object.
+ - If the granted permission is in response to a `PermissionRequest`, the object ****MUST**** contain a `permissionRequestId` property, and its value ****MUST**** be the [[spec:rfc4122]] UUID Version 4 string of the `PermissionRequest` object the permission is being granted in relation to.
+ - The object ****MUST**** contain a `grantedBy` property, and its value ****MUST**** be the DID URI string of the party that is granting the permission.
+ - The object ****MUST**** contain a `grantedTo` property, and its value ****MUST**** be the DID URI string of the party that is being granted the permission.
+ - If the `PermissionsGrant` is a delegated permission, the object ****MUST**** contain a `delegatedFrom` property, and its value ****MUST**** be an [[spec:rfc4122]] UUID Version 4 string matching the `permissionGrantId` of the `PermissionsGrant` it was delegated from.
+ - The object ****MUST**** contain a `expiry` property, and its value ****MUST**** be a [Unix epoch timestamp](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16) that can be used to trigger revocation activities.
+ - The object ****MUST**** contain a `scope` property, and its value ****Must**** be an object of the following properties:
+ - The object ****MUST**** contain an `interface` property, and its value ****MUST**** be the interface the requesting party wants to invoke.
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the interface method the requesting party wants to invoke.
+ - The object ****MAY**** contain a `schema` property, and its value ****Must**** be a URI string that indicates the schema of the associated data.
+ - The object ****MAY**** contain a `protocol` property, and its value ****Must**** be a URI that denotes the Protocol an object is a part of.
+ - The object ****MAY**** contain a `protocolVersion` property, and its value ****Must**** be a [SemVer](https://semver.org/) string that denotes the version of the Protocol the object is a part of.
+ - The object ****MAY**** contain a `recordId` property, and its value ****Must**** be a UUID 4 string reference to an object.
+ - The object ****MAY**** contain a `contextId` property, and its value ****Must**** be the deterministic ID for a contextually linked set of objects.
+ - The object ****MAY**** contain a [`conditions` property](#permission-conditions){ id=permission-conditions }, and its value ****Must**** be an object of the following properties:
+ - The object ****MAY**** contain an `attestation` property, and if present its value ****Must**** be a `string` representing the signing conditions detailed below. If the property is not present it ****MUST**** be evaluated as if it were set to the value `optional`.
+ - `prohibited` - the object ****MUST NOT**** be signed.
+ - `optional` - the object ****MAY**** be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+ - `required` - the object ****MUST**** be signed using a key linked to the DID of the owner of a Decentralized Web Node or authoring party (whichever is relevant to the application-level use case).
+ - The object ****MAY**** contain an `encryption` property, and if present its value ****Must**** be a `string` representing the encryption conditions detailed below. If the property is not present it ****MUST**** be evaluated as if it were set to the value `optional`.
+ - `optional` - the object ****MAY**** be encrypted using the key provided by the owner of a Decentralized Web Node in the [[spec:rfc7516]] JSON Web Encryption (JWE) format.
+ - `required` - the object ****MUST**** be encrypted using the key provided by the owner of a Decentralized Web Node in the [[spec:rfc7516]] JSON Web Encryption (JWE) format.
+ - The object ****MAY**** contain a `delegation` property, and its value ****Must**** be a boolean, wherein `true` indicates the issuing party is allowing the grantee the ability to delegate the capability. A value of `false` or omission of the property ****MUST**** be evaluated as false, and indicates the grantee ****MUST NOT**** be allowed to delegate the capability.
+ - The object ****MAY**** contain a `publication` property, and its value ****Must**** be a boolean, wherein `true` indicates the issuing party is allowing the grantee the ability to publish data tied to methods that support the `public` boolean value in their descriptor field sets. Conforming implementations ****MUST**** throw an error and fail to grant a permission if this property is present and the `method` does not support publication.
+ - The object ****MAY**** contain a `sharedAccess` property, and its value ****Must**** be a boolean, wherein `true` indicates the requesting
+ party wants the ability to use the permission against any object or data that aligns with the capability's definition, regardless of which
+ entity created the object or data. A value of `false` or omission of the property ****MUST**** be evaluated as false, and indicates the
+ requesting party only needs the ability to invoke the permission against objects or data it creates.
+- The message object ****MUST**** contain an `authorization` property, which ****MUST**** be a JSON object as defined by the [Message Authorization](#message-authorization)
+ section of this specification, with the requirement that the `kid` and `signature` ****MUST**** match the DID of the requesting party.
+- The message ****MUST**** contain a `data` payload, which is a JSON Web Token representation of the granted permission, as defined in the [Capability Objects](#capability-objects) section below.
+- The message ****MUST**** contain an `encryptionKey` property if the data transacted using the permission grant is to be encrypted, per the directives for encryption under the `encryption` field of the permission's [conditions](#permission-conditions). If present, the value of the `encryptionKey` property ****MUST**** be a [[spec:rfc7516]] JSON Web Encryption (JWE) object that contains the encrypted key material required for an authorized party to decrypt the JWE represented by the `dataCid` value within the `descriptor` object.
+
+```json
+{
+ "descriptor": {
+ "interface": "Permissions",
+ "method": "Grant",
+ "permissionGrantId": "f45wve-5b56v5w-5657b4e-56gqf35v",
+ "permissionRequestId": "b6464162-84af-4aab-aff5-f1f8438dfc1e",
+ "grantedBy": "did:example:bob",
+ "grantedTo": "did:example:carol",
+ "expiry": 1575606941,
+ "delegatedFrom": PARENT_PERMISSION_GRANT,
+ "scope": {
+ "method": "RecordsWrite",
+ "schema": "https://schema.org/MusicPlaylist",
+ "recordId": "f45wve-5b56v5w-5657b4e-56gqf35v"
+ },
+ "conditions": {
+ "delegation": true,
+ "publication": true,
+ "sharedAccess": true,
+ "encryption": "optional",
+ "attestation": "prohibited"
+ }
+ },
+ "authorization": {
+ "payload": "89f5hw458fhw958fq094j9jdq0943j58jfq09j49j40f5qj30jf",
+ "signatures": [{
+ "protected": "4d093qj5h3f9j204fq8h5398hf9j24f5q9h83402048h453q",
+ "signature": "49jq984h97qh3a49j98cq5h38j09jq9853h409jjq09h5q9j4"
+ }]
+ },
+ "encryptionKey": {
+ "protected": ...,
+ "recipients": ...,
+ "ciphertext": ...,
+ "iv": ...,
+ "tag": ...
+ }
+}
+```
+
+##### Granted Encryption Keys
+
+The `encryptionKey` attribute of a `PermissionsGrant` is a [[spec:rfc7516]] JSON Web Encryption (JWE) object that is composed as follows:
+
+1. The `kid` field of the JWE header ****MUST**** be a DID URL that identifies the public key type designated for encryption in the DID Document of the `PermissionGrant` recipient.
+2. The `ciphertext` field ****MUST**** be encrypted with the `X25519` public key designated for encryption in the DID Document of the `PermissionGrant` recipient.
+3. The data encrypted in the object's `ciphertext` field ****MUST**** be the JSON Web Key (JWK) object representation of a `AES-256` symmetric encryption key generated by the owner of the DWeb Node that will be used to encrypt the data transacted in relation to the associated `PermissionGrant`.
+
+
+##### Grantor `PermissionsGrant` Storage
+
+After generating a `PermissionsGrant` the user agent (e.g. wallet app with access to authoritative keys for a given DID) ****MUST**** commit the granted permission object to the Decentralized Web Node of the DID the grant was issued from. This will ensure that the permission is present when addressed in subsequent interface method invocations.
+
+##### Grantee `PermissionsGrant` Delivery
+
+Once a user agent (e.g. wallet app with access to authoritative keys for a given DID) generates a `PermissionsGrant` for an entity to permit access to data and functionality, it is the responsibility of the user agent that generated the `PermissionsGrant` to deliver it to the entity that is the subject. To do this, the user agent ****MUST**** generate a Request that includes the `PermissionsGrant` and send it to the Decentralized Web Node of the subject it has been granted to, in accordance with the [Resolution](#resolution) and [Request Construction](#request-construction) sections of this specification.
+
+
+#### `PermissionsRevoke`
+
+Revocation of a permission is the act of closing off any additional or invalid invocations of that permission. The Revoke interface method enables revocation of a permission via direct reference to the permission's ID.
+
+```json
+{ // Message
+ "descriptor": { // Message Descriptor
+ "interface": "Permissions",
+ "method": "Revoke",
+ "permissionRevokeId": "sdfa4162-84af-4aab-aff5-f1f8438dfc1e",
+ "permissionGrantId": "b6464162-84af-4aab-aff5-f1f8438dfc1e"
+ }
+}
+```
+
+#### `PermissionsQuery`
+
+The `PermissionQuery` method exists to facilitate lookup of any retained Permissions objects that exist in a given DID's DWeb Node instance.
+
+```json
+{ // Message
+ "descriptor": { // Message Descriptor
+ "interface": "Permissions",
+ "method": "Query",
+ "grantedTo": "did:example:bob"
+ }
+}
+```
+
+- The message object ****MUST**** contain a `descriptor` property, and its value ****MUST**** be a JSON object composed as follows:
+ - The object ****MUST**** contain an `interface` property, and its value ****MUST**** be the string `Permissions`.
+ - The object ****MUST**** contain a `method` property, and its value ****MUST**** be the string `Query`.
+ - The object ****MAY**** contain any of the following properties from the descriptors of `PermissionsRequest`, `PermissionsGrant`, and `PermissionsRevoke` objects:
+ - `permissionRequestId`
+ - `permissionGrantId`
+ - `permissionRevokeId`
+ - `grantedBy`
+ - `grantedTo`
+ - `delegatedFrom`
+ - all properties of `scope` objects
+
+### Sync
+
+The Sync interface and its methods allow different Decentralized Web Nodes to communicate and sync on the state of the data they contain, including replication of messages and files.
+
+## Supported Encryption Schemes
+
+A conforming implementation ****MUST**** be capable of encrypting and decrypting data stored in Decentralized Web Nodes using the following combinations of cryptographic schemes. Each scheme is a pair, wherein the symmetric keys are used to encrypt the data being protected, then subsequently shared with permitted recipients via encryption of the symmetric keys using the asymmetric key of each recipient.
+
+| Asymmetric Key | Symmetric Key |
+| -------------- | ------------------- |
+| `X25519` | `AES-GCM` |
+| `X25519` | `XSalsa20-Poly1305` |
+
+## Supported Encryption Formats
+
+A conforming implementation ****MUST**** be capable of encrypting and decrypting data stored in Decentralized Web Nodes using the following combinations of cryptographic schemes. Each scheme is a pair, wherein the symmetric keys are used to encrypt the data being protected, then subsequently shared with permitted recipients via encryption of the symmetric keys using the asymmetric key of each recipient.
+
+| Label | Format |
+| -------- | ------------------- |
+| `jwe` | `AES-GCM` |
+| `X25519` | `XSalsa20-Poly1305` |
+
+## Normative References
+
+[[spec]]
diff --git a/specs.json b/specs.json
new file mode 100644
index 0000000..0ad6675
--- /dev/null
+++ b/specs.json
@@ -0,0 +1,56 @@
+
+{
+ "specs": [
+ {
+ "title": "DIF Decentralized Web Node",
+ "spec_directory": "./spec",
+ "output_path": "./spec/0.0.1-predraft",
+ "logo": "https://rawcdn.githack.com/decentralized-identity/decentralized-identity.github.io/a3ca39717e440302d1fd99a796e7f00e1c42eb2d/images/logo-flat.svg",
+ "logo_link": "https://identity.foundation",
+ "source": {
+ "host": "github",
+ "account": "decentralized-identity",
+ "repo": "decentralized-web-node"
+ }
+ },
+ {
+ "title": "DIF Decentralized Web Node",
+ "spec_directory": "./spec",
+ "output_path": "./spec",
+ "logo": "https://rawcdn.githack.com/decentralized-identity/decentralized-identity.github.io/a3ca39717e440302d1fd99a796e7f00e1c42eb2d/images/logo-flat.svg",
+ "logo_link": "https://identity.foundation",
+ "source": {
+ "host": "github",
+ "account": "decentralized-identity",
+ "repo": "decentralized-web-node"
+ }
+ },
+ {
+ "title": "DIF Decentralized Web Node",
+ "spec_directory": "./spec",
+ "output_path": "./",
+ "logo": "https://rawcdn.githack.com/decentralized-identity/decentralized-identity.github.io/a3ca39717e440302d1fd99a796e7f00e1c42eb2d/images/logo-flat.svg",
+ "logo_link": "https://identity.foundation",
+ "source": {
+ "host": "github",
+ "account": "decentralized-identity",
+ "repo": "decentralized-web-node"
+ }
+ },
+ {
+ "title": "Decentralized Web Node Companion Guide",
+ "spec_directory": "./docs",
+ "output_path": "./guide/v0.0.1",
+ "markdown_paths": [
+ "companion_guide.md"
+ ],
+ "logo": "https://rawcdn.githack.com/decentralized-identity/decentralized-identity.github.io/a3ca39717e440302d1fd99a796e7f00e1c42eb2d/images/logo-flat.svg",
+ "logo_link": "https://identity.foundation",
+ "source": {
+ "host": "github",
+ "account": "decentralized-identity",
+ "repo": "decentralized-web-node"
+ }
+ }
+ ]
+}