on master help sign in
Merge pull request #1162 from tinnus-napbus/update-graph-store-diagrams
e88aa00tinnus-napbus
content/docs/userspace/graph-store/overview.md+15−21
@@ -6,52 +6,47 @@ template = "doc.html"
6insert_anchor_links = "right"
6insert_anchor_links = "right"
7+++
7+++
8
8
9−
10## Intro
9## Intro
10+
11Graph store is a non-relational database suitable for use in building social media applications. It is primarily designed for storing text-based content and data that is generally threaded and nested. It is not suitable as a general purpose database for highly structured or pure binary data.
11Graph store is a non-relational database suitable for use in building social media applications. It is primarily designed for storing text-based content and data that is generally threaded and nested. It is not suitable as a general purpose database for highly structured or pure binary data.
12
12
13−<p align="center">
14− <img src="https://media.urbit.org/docs/userspace/graph-store/1_graph_store_overview.png"/>
13+![Graph Store Overview Diagram](https://media.urbit.org/docs/userspace/graph-store/1_graph_store_overview.svg)
15−</p>
16
14
17Graph Store is mainly in charge of two things: data storage and retrieval, and schema validation. There are two related tools: Graph Push Hook, which provides permissioning support to Graph Store and acts as a proxy layer to Graph Store for outside ships to access, and Graph Pull Hook, which can be used to request Graph Store data from other ships. Importantly, Graph Store itself does not have a built-in permissions system (or rather, is permissions-agnostic), and acts in a purely trusted manner, and assumes that all inputs are trusted. However, it only allows local, authenticated connections to communicate with it, meaning that by default, no one else on the network may modify the state of your Graph Store agent. This is why Graph Push Hook exists: to mediate untrusted requests from outside ships to your instance of Graph Store, rejecting invalid ones where a ship should not be able to modify the data.
15Graph Store is mainly in charge of two things: data storage and retrieval, and schema validation. There are two related tools: Graph Push Hook, which provides permissioning support to Graph Store and acts as a proxy layer to Graph Store for outside ships to access, and Graph Pull Hook, which can be used to request Graph Store data from other ships. Importantly, Graph Store itself does not have a built-in permissions system (or rather, is permissions-agnostic), and acts in a purely trusted manner, and assumes that all inputs are trusted. However, it only allows local, authenticated connections to communicate with it, meaning that by default, no one else on the network may modify the state of your Graph Store agent. This is why Graph Push Hook exists: to mediate untrusted requests from outside ships to your instance of Graph Store, rejecting invalid ones where a ship should not be able to modify the data.
18
16
19## Data Structures
17## Data Structures
18+
20### Posts
19### Posts
21
20
22−<p align="center">
23− <img src="https://media.urbit.org/docs/userspace/graph-store/2_post_diagram.png"/>
21+![Post Diagram](https://media.urbit.org/docs/userspace/graph-store/2_post_diagram.svg)
24−</p>
25
22
26Above, we can see a representation of a post on the left, along with its table form on the right.
23Above, we can see a representation of a post on the left, along with its table form on the right.
27A post is the most basic building block of a graph.
24A post is the most basic building block of a graph.
28Every post is made up of an:
25Every post is made up of an:
26+
29- **Author** - who created the post
27- **Author** - who created the post
30- **Index** - the unique path/identifier of the post on the graph (more on this later)
28- **Index** - the unique path/identifier of the post on the graph (more on this later)
31- **Time Sent** - when the post was created
29- **Time Sent** - when the post was created
32- **Contents** - data that the user intended to post
30- **Contents** - data that the user intended to post
33
31
34Currently, Graph Store supports 5 data types for content that is to be stored within a graph:
32Currently, Graph Store supports 5 data types for content that is to be stored within a graph:
33+
35- **Text** - plain text data
34- **Text** - plain text data
36- **Url** - specific data type for urls
35- **Url** - specific data type for urls
37- **Mention** - mentioning another ship
36- **Mention** - mentioning another ship
38- **Code** - a pair of a piece of code that was executed and its result (this is static data, and is not used to execute code on other's ships)
37- **Code** - a pair of a piece of code that was executed and its result (this is static data, and is not used to execute code on other's ships)
39- **Reference** - a reference to another post
38- **Reference** - a reference to another post
40
39
41−
42### Graphs and Nodes
40### Graphs and Nodes
43
41
44−<p align="center">
45− <img src="https://media.urbit.org/docs/userspace/graph-store/3_graph_node_diagram_a.png"/>
42+![Graph Node Diagram A](https://media.urbit.org/docs/userspace/graph-store/3_graph_node_diagram_a.svg)
46−</p>
47
43
48−<p align="center">
49− <img src="https://media.urbit.org/docs/userspace/graph-store/4_graph_node_diagram_b.png"/>
44+![Graph Node Diagram B](https://media.urbit.org/docs/userspace/graph-store/4_graph_node_diagram_b.svg)
50−</p>
51
45
52A graph is a flat, ordered map of nodes, where each node can have a child graph, which is itself a flat ordered map of nodes. Nodes contain a post and a child graph. In the above diagram, we can see an example of a basic graph on the top, along with the underlying structure of the data in table form underneath.
46A graph is a flat, ordered map of nodes, where each node can have a child graph, which is itself a flat ordered map of nodes. Nodes contain a post and a child graph. In the above diagram, we can see an example of a basic graph on the top, along with the underlying structure of the data in table form underneath.
53
47
54A few vocab terms:
48A few vocab terms:
49+
55- **Root graph** refers to the outermost graph, G in this case
50- **Root graph** refers to the outermost graph, G in this case
56- **Top level** is a loose term usually used to refer to a node that exists in the root graph. **A** and **D** would be considered nodes at the top level, but **B** and all its descendants would not qualify.
51- **Top level** is a loose term usually used to refer to a node that exists in the root graph. **A** and **D** would be considered nodes at the top level, but **B** and all its descendants would not qualify.
57- **Sibling nodes** are two nodes that reside next to each other, meaning that they reside in the same `graph`. **A** and **D** are an example of sibling nodes.
52- **Sibling nodes** are two nodes that reside next to each other, meaning that they reside in the same `graph`. **A** and **D** are an example of sibling nodes.
@@ -62,27 +57,23 @@ A few vocab terms:
62
57
63### Index
58### Index
64
59
65−<p align="center">
66− <img src="https://media.urbit.org/docs/userspace/graph-store/5_index_diagram.png"/>
60+![Index Diagram](https://media.urbit.org/docs/userspace/graph-store/5_index_diagram.svg)
67−</p>
68
61
69Indexes are a way of uniquely identifying a node within a graph. You can think of `index`es as similar to file paths, although they aren't exactly the same. Roughly, a file path is a unique reference to a file or folder located in the filesystem. Similarly, an index is a unique reference to a node nested within a graph. The written syntax for a full index is very similar to file paths. It consists of every index fragment in order separated by a slash. A node's **level of nesting** refers to how deeply it is nested within the context of the root graph. The level of nesting directly corresponds to the number of items in the index. An index fragment is the atom by which a node is uniquely identified within it's graph, and roughly corresponds to a specific name of a directory along a path. In the diagrams that follow, we'll use the index fragment instead of the index to avoid repeating redundant information, but please note that internally graph-store still store the full index in every node's post.
62Indexes are a way of uniquely identifying a node within a graph. You can think of `index`es as similar to file paths, although they aren't exactly the same. Roughly, a file path is a unique reference to a file or folder located in the filesystem. Similarly, an index is a unique reference to a node nested within a graph. The written syntax for a full index is very similar to file paths. It consists of every index fragment in order separated by a slash. A node's **level of nesting** refers to how deeply it is nested within the context of the root graph. The level of nesting directly corresponds to the number of items in the index. An index fragment is the atom by which a node is uniquely identified within it's graph, and roughly corresponds to a specific name of a directory along a path. In the diagrams that follow, we'll use the index fragment instead of the index to avoid repeating redundant information, but please note that internally graph-store still store the full index in every node's post.
70
63
71In the above diagram, we would say that nodes **A** and **D** are nested 1 level deep, while **B** would be at the 2nd level of nesting, and **C** would be nested 3 levels deep.
64In the above diagram, we would say that nodes **A** and **D** are nested 1 level deep, while **B** would be at the 2nd level of nesting, and **C** would be nested 3 levels deep.
72
65
73Indexes are usually numbers and are stored as such in the database. Most commonly, they can represent:
66Indexes are usually numbers and are stored as such in the database. Most commonly, they can represent:
67+
74- Date or time of posting
68- Date or time of posting
75- A sequence of numbers starting from 1 increasing
69- A sequence of numbers starting from 1 increasing
76- Structural/constant value: values which are associated with a specific meaning in the context of the schema of an application.
70- Structural/constant value: values which are associated with a specific meaning in the context of the schema of an application.
77
71
78However, there is no strict requirement for them to be numbers; they can be cords as well as other data types. As we'll see in the later sections, it is up to the app developer to decide this when creating their application.
72However, there is no strict requirement for them to be numbers; they can be cords as well as other data types. As we'll see in the later sections, it is up to the app developer to decide this when creating their application.
79
73
80−
81### Structural Nodes vs. Content-Centric Nodes
74### Structural Nodes vs. Content-Centric Nodes
82
75
83−<p align="center">
84− <img src="https://media.urbit.org/docs/userspace/graph-store/6_structural_vs_content_centric_diagram.png"/>
76+![Structural vs Content-centric Diagram](https://media.urbit.org/docs/userspace/graph-store/6_structural_vs_content_centric_diagram.svg)
85−</p>
86
77
87When using Graph Store, there is a notion of **structural nodes** vs. **content-centric nodes**. In the example diagram, we've color coded the different nodes based on what type of node they are. **Content-centric nodes** represent data created or consumed directly by the user. **Structural nodes**, on the other hand do not directly represent user data, and instead represent a higher level relationship between different user data. Structural nodes are used to implement the structure of the schema that is being implemented. In other words, they exist away from the eyes of the user, solely for organizational purposes.
78When using Graph Store, there is a notion of **structural nodes** vs. **content-centric nodes**. In the example diagram, we've color coded the different nodes based on what type of node they are. **Content-centric nodes** represent data created or consumed directly by the user. **Structural nodes**, on the other hand do not directly represent user data, and instead represent a higher level relationship between different user data. Structural nodes are used to implement the structure of the schema that is being implemented. In other words, they exist away from the eyes of the user, solely for organizational purposes.
88
79
@@ -95,15 +86,18 @@ Every social application has a minimum amount of information it needs to functio
95In addition, validators can also encode structural permissions. **Structural permissions** govern who is allowed to add or remove a given node (and by extension modify its children) based on the node's characteristics.
86In addition, validators can also encode structural permissions. **Structural permissions** govern who is allowed to add or remove a given node (and by extension modify its children) based on the node's characteristics.
96
87
97There are 3 different classes of users:
88There are 3 different classes of users:
89+
98- **Admin** - An owner of a resource or someone who's been delegated similar privileges
90- **Admin** - An owner of a resource or someone who's been delegated similar privileges
99- **Writer** - Someone who can create and modify their own content but cannot modify others'
91- **Writer** - Someone who can create and modify their own content but cannot modify others'
100- **Reader** - Someone who is only given permission to access but not create or modify, except in special cases
92- **Reader** - Someone who is only given permission to access but not create or modify, except in special cases
101
93
102There are two different types of privileges:
94There are two different types of privileges:
95+
103- **Add privileges** - permission to create a given node and create any child nodes
96- **Add privileges** - permission to create a given node and create any child nodes
104- **Remove privileges** - permission to remove a given node and remove any of its children
97- **Remove privileges** - permission to remove a given node and remove any of its children
105
98
106There are also three different levels of access a given permission level can have:
99There are also three different levels of access a given permission level can have:
100+
107- **%no** - user does not have add or remove privileges for this node
101- **%no** - user does not have add or remove privileges for this node
108- **%yes** - user has add or remove privileges for this node, whether or not they authored the parent node
102- **%yes** - user has add or remove privileges for this node, whether or not they authored the parent node
109- **%self** - user has add or remove privileges for child nodes only if they authored the parent node (determined by `author` of post, i.e., they are the author of the post)
103- **%self** - user has add or remove privileges for child nodes only if they authored the parent node (determined by `author` of post, i.e., they are the author of the post)
content/docs/userspace/graph-store/sample-application-overview.md+58−58
@@ -6,28 +6,26 @@ template = "doc.html"
6insert_anchor_links = "right"
6insert_anchor_links = "right"
7+++
7+++
8
8
9−
10−
11−Library is a sample social media application in which you can create a collection of books, called a library, which can contain any number of books.
9+Library is a sample social media application in which you can create a collection of books, called a library, which can contain any number of books.
12−You can share individual collections per-ship. The creator of the collection has de-facto admin powers; he is the only one who can add or remove books to/from the library,
10+You can share individual collections per-ship. The creator of the collection has de-facto admin powers; he is the only one who can add or remove books to/from the library,
13−remove the library itself, and add comments or remove anyone's comments. Guest ships may request access to specific libraries, which if granted,
11+remove the library itself, and add comments or remove anyone's comments. Guest ships may request access to specific libraries, which if granted,
14allows them to request any book from the library.
12allows them to request any book from the library.
15
13
16Using this application, you can:
14Using this application, you can:
17
15
18−- Create libraries, where a library is a collection of books
16+- Create libraries, where a library is a collection of books
19−- Add and remove books from a library, if you are the owner
17+- Add and remove books from a library, if you are the owner
20−- Allow others to view your library based on various permissioning schemes (policies)
18+- Allow others to view your library based on various permissioning schemes (policies)
21−- Add and remove comments from a library, if you are the owner or were granted access
19+- Add and remove comments from a library, if you are the owner or were granted access
22
20
23## Prerequisites
21## Prerequisites
24
22
25−This overview is a companion document to the *Library* application, and assumes you are familiar with `%graph-store`. Before continuing, **you must familiarize yourself with the sample application**, which can be found [here](https://github.com/ynx0/library). See the [detailed usage guide](https://github.com/ynx0/library/blob/master/README.md) for download and installation instructions.
23+This overview is a companion document to the _Library_ application, and assumes you are familiar with `%graph-store`. Before continuing, **you must familiarize yourself with the sample application**, which can be found [here](https://github.com/ynx0/library). See the [detailed usage guide](https://github.com/ynx0/library/blob/master/README.md) for download and installation instructions.
26−
27
24
28## Project Structure
25## Project Structure
29
26
30Here is the directory structure of our app.
27Here is the directory structure of our app.
28+
31```
29```
32├── app
30├── app
33│ └── library-proxy.hoon
31│ └── library-proxy.hoon
@@ -58,29 +56,28 @@ Here is the directory structure of our app.
58
56
59- [`install.sh`](https://github.com/ynx0/library/blob/master/install.sh) is a script that automates copying the source files into a ship's pier / home desk.
57- [`install.sh`](https://github.com/ynx0/library/blob/master/install.sh) is a script that automates copying the source files into a ship's pier / home desk.
60
58
61−
62## Implementation Summary
59## Implementation Summary
63
60
64The project contains a custom `%graph-store` validator tht specifies the application's schema and a custom gall agent, called `%library-proxy`, which sends `%graph-store` updates between the host ship and subscribers.
61The project contains a custom `%graph-store` validator tht specifies the application's schema and a custom gall agent, called `%library-proxy`, which sends `%graph-store` updates between the host ship and subscribers.
65−The gall agent also generates `%graph-store` updates based on commands and actions that a user issues. Commands can only be issued to a proxy by the ship owner,
62+The gall agent also generates `%graph-store` updates based on commands and actions that a user issues. Commands can only be issued to a proxy by the ship owner,
66−while actions can be issued by any ship, but may fail based on permissions. A host ship's `%library-proxy` talks to the subscriber ship's `%library-proxy` through the normal gall app channels (pokes/peeks)
63+while actions can be issued by any ship, but may fail based on permissions. A host ship's `%library-proxy` talks to the subscriber ship's `%library-proxy` through the normal gall app channels (pokes/peeks)
67−to send them any updates that have taken place on the library graph. It is the host's responsibility to forward all relevant updates to subscribers
64+to send them any updates that have taken place on the library graph. It is the host's responsibility to forward all relevant updates to subscribers
68(kept track of in a data structure defined [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/sur/library.hoon#L14-L15)),
65(kept track of in a data structure defined [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/sur/library.hoon#L14-L15)),
69while subscribers must only trust graph updates that it receives from the owner of that resource.
66while subscribers must only trust graph updates that it receives from the owner of that resource.
70
67
71Here are the proxy's responsibilities:
68Here are the proxy's responsibilities:
72
69
73−- **Application-specific API** - presents an interface for a user to interact with both his/her own library proxy and others' by directly defining and implementing a user-facing API as pokes and scries,
70+- **Application-specific API** - presents an interface for a user to interact with both his/her own library proxy and others' by directly defining and implementing a user-facing API as pokes and scries,
74− as opposed to forcing the user to deal with the graph-store API directly. The `command`/`action`/`response` poke types are defined [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/sur/library.hoon#L17-L42),
71+ as opposed to forcing the user to deal with the graph-store API directly. The `command`/`action`/`response` poke types are defined [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/sur/library.hoon#L17-L42),
75− while the scries are defined [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/app/library-proxy.hoon#L132).
72+ while the scries are defined [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/app/library-proxy.hoon#L132).
76−- **Graph store update creation** - creates the appropriate graph update for a given user-facing action
73+- **Graph store update creation** - creates the appropriate graph update for a given user-facing action
77−- **Graph store update proxying** - handles the networking and subscription logic required to send graph store updates between host and subscriber
74+- **Graph store update proxying** - handles the networking and subscription logic required to send graph store updates between host and subscriber
78−- **Access control** - allows or denies ships access to libraries, checks for proper permissions before processing a `command` or `action`
75+- **Access control** - allows or denies ships access to libraries, checks for proper permissions before processing a `command` or `action`
79
76
80## Interaction with `%graph-store`
77## Interaction with `%graph-store`
81
78
82There are a couple of ways that our application uses and interacts with `%graph-store`.
79There are a couple of ways that our application uses and interacts with `%graph-store`.
83−Firstly, the app subscribes to `%graph-store` in `+on-init` on path `/updates`, meaning it will be notified of every single `graph-update` that occurs on the local ship. (*Recall the type of `graph-update`, defined [here](https://github.com/urbit/urbit/blob/ceed4b78d068d7cb70350b3cd04e7525df1c7e2d/pkg/arvo/sur/graph-store.hoon#L29), the reference for which can be found [here](https://urbit.org/docs/userspace/graph-store/data-structure-overview/#update-part-1)*). We also define a validator for our application that `%graph-store` uses for every *Library* graph. Since `%graph-store` registers all validators under the path `%/graph/validator/<name of app>/hoon`, we don't have to do anything special to register our validator. We just need to correctly name our file, and provide an `+graph-indexed-post` arm which should perform all schema validation.
80+Firstly, the app subscribes to `%graph-store` in `+on-init` on path `/updates`, meaning it will be notified of every single `graph-update` that occurs on the local ship. (_Recall the type of `graph-update`, defined [here](https://github.com/urbit/urbit/blob/ceed4b78d068d7cb70350b3cd04e7525df1c7e2d/pkg/arvo/sur/graph-store.hoon#L29), the reference for which can be found [here](https://urbit.org/docs/userspace/graph-store/data-structure-overview/#update-part-1)_). We also define a validator for our application that `%graph-store` uses for every _Library_ graph. Since `%graph-store` registers all validators under the path `%/graph/validator/<name of app>/hoon`, we don't have to do anything special to register our validator. We just need to correctly name our file, and provide an `+graph-indexed-post` arm which should perform all schema validation.
84
81
85### Synchronizing Graphs Between Ships
82### Synchronizing Graphs Between Ships
86
83
@@ -88,7 +85,7 @@ An owner is responsible for forwarding any updates to clients. Whenever the `%li
88
85
89On the receiving end, since we know that we are not the source of the `graph-update`, we handle the update in the `handle-incoming-graph-store` helper arm, which makes sure to only process and forward graph store updates to local graph store that are sent by the owner, and no one else. Once it passes this permissions check, it is poked into the local graph like any other graph-update.
86On the receiving end, since we know that we are not the source of the `graph-update`, we handle the update in the `handle-incoming-graph-store` helper arm, which makes sure to only process and forward graph store updates to local graph store that are sent by the owner, and no one else. Once it passes this permissions check, it is poked into the local graph like any other graph-update.
90
87
91−\**One could imagine a gossip style protocol where the data is like a fact so it doesn't matter where it came from, but in this app the library host is defined as the source of truth.*
88+\*_One could imagine a gossip style protocol where the data is like a fact so it doesn't matter where it came from, but in this app the library host is defined as the source of truth._
92
89
93## Data Model
90## Data Model
94
91
@@ -99,7 +96,7 @@ meant to represent a comment on any given book.
99
96
100### Representing Data using `%graph-store`
97### Representing Data using `%graph-store`
101
98
102−The data types we defined for our application do not fit within `%graph-store` out of the box. `%graph-store` doesn't allow arbitrarily typed data in a node's content field, so we create an ad-hoc representation that we can cleanly convert to and from our own data types and `%graph-store` types.
99+The data types we defined for our application do not fit within `%graph-store` out of the box. `%graph-store` doesn't allow arbitrarily typed data in a node's content field, so we create an ad-hoc representation that we can cleanly convert to and from our own data types and `%graph-store` types.
103
100
104Here is the conversion code: [(link)](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/lib/library.hoon#L12-L19)
101Here is the conversion code: [(link)](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/lib/library.hoon#L12-L19)
105
102
@@ -120,28 +117,28 @@ Each arm takes in either a `book` or a `comment`, our application specific data
120
117
121We define 3 core structures:
118We define 3 core structures:
122
119
123−- **Library** - The fundamental data structure. A library is a graph that contains books
120+- **Library** - The fundamental data structure. A library is a graph that contains books
124−- **Book** - A data structure that contains an entry of a given book's metadata (i.e. title and isbn) and any comments associated with it. It is represented by a top-level node within a library graph
121+- **Book** - A data structure that contains an entry of a given book's metadata (i.e. title and isbn) and any comments associated with it. It is represented by a top-level node within a library graph
125−- **Comment** - A node that represents a user's comment on a given book. Represented as a child node of a book's comment container node.
122+- **Comment** - A node that represents a user's comment on a given book. Represented as a child node of a book's comment container node.
126
123
127We then define the layout of the data as follows:
124We then define the layout of the data as follows:
128
125
129−* Library
126+- Library
130− - Book
127+ - Book
131− + Metadata Revision Container
128+ - Metadata Revision Container
132− * Specific Metadata Revision
129+ - Specific Metadata Revision
133− + Comments Container
130+ - Comments Container
134− * Specific Comment
131+ - Specific Comment
135
132
136−Every graph created with the `%graph-validator-library` is a *Library* graph, and thus it has the following characteristics:
133+Every graph created with the `%graph-validator-library` is a _Library_ graph, and thus it has the following characteristics:
137
134
138−- Every Library graph represents a library, or a collection of books
135+- Every Library graph represents a library, or a collection of books
139−- Every top level node in a library represents a book and all related contents
136+- Every top level node in a library represents a book and all related contents
140−- Within a book there are always two structural nodes: a container node for metadata revisions, and a container node that holds all comments, modeling a comments section
137+- Within a book there are always two structural nodes: a container node for metadata revisions, and a container node that holds all comments, modeling a comments section
141
138
142To make things more concrete, let's look at an example of an actual graph.
139To make things more concrete, let's look at an example of an actual graph.
143
140
144−(*For the sake of clarity, we have replaced each index with its representation in its original aura in following output.*)
141+(_For the sake of clarity, we have replaced each index with its representation in its original aura in following output._)
145
142
146```
143```
147[ p=[entity=~zod name=%library1]
144[ p=[entity=~zod name=%library1]
@@ -261,17 +258,17 @@ To make things more concrete, let's look at an example of an actual graph.
261]
258]
262```
259```
263
260
264−![](https://lh5.googleusercontent.com/UTCnXumWvuPpFtduxgzmxIR_vhn9N3SylJ9h-MoUjYWiCT4AZo4BXY1mWceu0iHcJjesWoBDzMVO9QYWbnqtsGWa4nt4GlIRAtiC2zSXLkDUEttTmlMDLS7XRZ7ZhJyEayaMMl2r)
261+![Library App Schema Diagram](https://media.urbit.org/docs/userspace/graph-store/library-app-schema-diagram.svg)
265
262
266−* The above graph represents a library that has a single book, whose metadata is stored under the `%meta` revision container. The metadata associated with this specific book entry is currently with title: `"Dune"` and isbn `"0441172717"`.
263+- The above graph represents a library that has a single book, whose metadata is stored under the `%meta` revision container. The metadata associated with this specific book entry is currently with title: `"Dune"` and isbn `"0441172717"`.
267 The reason we have a revision container for the book metadata is so that in case someone makes an error, they may correct it. A potential frontend could then simply show the most recent version.
264 The reason we have a revision container for the book metadata is so that in case someone makes an error, they may correct it. A potential frontend could then simply show the most recent version.
268−* Each comment is simply a node under a book's `%comment` node with a single `%text` content.
265+- Each comment is simply a node under a book's `%comment` node with a single `%text` content.
269 We skipped revision containers for comments to keep schema simple, but you could imagine duplicating the same logic for comments as well.
266 We skipped revision containers for comments to keep schema simple, but you could imagine duplicating the same logic for comments as well.
270−* Every book node has an index the datetime of when it was created.
267+- Every book node has an index the datetime of when it was created.
271−* Each structural node in a book has a constant index fragment, either `%meta` for the metadata revision container node,
268+- Each structural node in a book has a constant index fragment, either `%meta` for the metadata revision container node,
272 or `%comments` for the comments container node.
269 or `%comments` for the comments container node.
273−* Every comment has an index of the datetime of when it was posted.
270+- Every comment has an index of the datetime of when it was posted.
274−* The metadata revisions are a single incrementing number starting from 1, so the initial metadata has a revision count of `1`, and a subsequent edit has a revision count of `2`, and so on.
271+- The metadata revisions are a single incrementing number starting from 1, so the initial metadata has a revision count of `1`, and a subsequent edit has a revision count of `2`, and so on.
275
272
276### Schema Enforcement
273### Schema Enforcement
277
274
@@ -280,12 +277,12 @@ Take a moment to read through it and cross-check your understanding with the fol
280
277
281**Validator logic summary**
278**Validator logic summary**
282
279
283−- None of the structural nodes require data, so we simply assert that their contents are empty
280+- None of the structural nodes require data, so we simply assert that their contents are empty
284−- For a *Specific Comment Node*, a post with an index matching the structure `[@ %comments @ ~]`, we assert that `contents` only contains a single `%text` content.
281+- For a _Specific Comment Node_, a post with an index matching the structure `[@ %comments @ ~]`, we assert that `contents` only contains a single `%text` content.
285− This choice is arbitrary but meant to keep the application simple and so that a potential frontend does not have to do complex rendering.
282+ This choice is arbitrary but meant to keep the application simple and so that a potential frontend does not have to do complex rendering.
286−- For a *Specific Metadata Revision*, a post with index matching the structure `[@ %meta @ ~]`, we first ensure that it's contents only contain two `%text` content instances.
283+- For a _Specific Metadata Revision_, a post with index matching the structure `[@ %meta @ ~]`, we first ensure that it's contents only contain two `%text` content instances.
287− We then use two helper arms `+is-title-valid` and `+is-isbn-valid` to validate the two values. For us, any title value is accepted, while only strings with length 10 or 13 are valid ISBNs.
284+ We then use two helper arms `+is-title-valid` and `+is-isbn-valid` to validate the two values. For us, any title value is accepted, while only strings with length 10 or 13 are valid ISBNs.
288− (We don't do any true ISBN validation for simplicity's sake)
285+ (We don't do any true ISBN validation for simplicity's sake)
289
286
290## Access Control
287## Access Control
291
288
@@ -296,6 +293,7 @@ which are set by the user per-library at the time of creation (stored [here](htt
296These specify who can or cannot gain access to a library.
293These specify who can or cannot gain access to a library.
297
294
298Here's what `policy` looks like:
295Here's what `policy` looks like:
296+
299```
297```
300+$ policy
298+$ policy
301 $% [%open ~] :: any ship is allowed
299 $% [%open ~] :: any ship is allowed
@@ -307,13 +305,14 @@ Here's what `policy` looks like:
307There are also implicit rules, defined as follows:
305There are also implicit rules, defined as follows:
308
306
309For any given library that one owns,
307For any given library that one owns,
308+
310- An owner can:
309- An owner can:
311− + add a top level book node to any library
310+ - add a top level book node to any library
312− + add a metadata revision to any book
311+ - add a metadata revision to any book
313− + add or remove any comment on any book
312+ - add or remove any comment on any book
314- A reader, that is, a another ship granted access to the library, can:
313- A reader, that is, a another ship granted access to the library, can:
315− + add a comment to any book that they have requested
314+ - add a comment to any book that they have requested
316− + remove any comment that they are the author of
315+ - remove any comment that they are the author of
317
316
318Implicitly, all readers are given permission to get any book when granted access to the library.
317Implicitly, all readers are given permission to get any book when granted access to the library.
319
318
@@ -323,6 +322,7 @@ Implicitly, all readers are given permission to get any book when granted access
323
322
324- The `+is-allowed` arm, (found [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/lib/library.hoon#L21))
323- The `+is-allowed` arm, (found [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/lib/library.hoon#L21))
325 implements each `policy`'s behavior, and is reproduced below.
324 implements each `policy`'s behavior, and is reproduced below.
325+
326 ```
326 ```
327 ++ is-allowed
327 ++ is-allowed
328 |= [requester=ship host=ship =policy:library]
328 |= [requester=ship host=ship =policy:library]
@@ -335,8 +335,8 @@ Implicitly, all readers are given permission to get any book when granted access
335 %whitelist (~(has in ships.policy) requester)
335 %whitelist (~(has in ships.policy) requester)
336 ==
336 ==
337 ```
337 ```
338− Given the host ship of a resource and the policy to be enforced for a resource, `+is-allowed` returns a boolean for whether or not a requesting ship should be allowed access to that resource.
339
338
339+ Given the host ship of a resource and the policy to be enforced for a resource, `+is-allowed` returns a boolean for whether or not a requesting ship should be allowed access to that resource.
340
340
341- `+is-allowed` is used in `+on-watch` [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/app/library-proxy.hoon#L113), where it only allows a ship to subscribe to a library if it passes the permissions check.
341- `+is-allowed` is used in `+on-watch` [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/app/library-proxy.hoon#L113), where it only allows a ship to subscribe to a library if it passes the permissions check.
342- It is also used [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/app/library-proxy.hoon#L299) and [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/app/library-proxy.hoon#L310), so that when a ship wants to know about what libraries and books exist, only data they are allowed to see gets revealed to them.
342- It is also used [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/app/library-proxy.hoon#L299) and [here](https://github.com/ynx0/library/blob/9104145bb24e8ec949a5e9685139665b07161dd6/app/library-proxy.hoon#L310), so that when a ship wants to know about what libraries and books exist, only data they are allowed to see gets revealed to them.
@@ -354,7 +354,7 @@ The permissioning scheme was also implemented relatively simple; it has some lim
354### Comparison between `%library-proxy` and `%graph-push-hook`
354### Comparison between `%library-proxy` and `%graph-push-hook`
355
355
356`%library-proxy` performs the functions of both `%graph-push-hook` and `%graph-pull-hook`.
356`%library-proxy` performs the functions of both `%graph-push-hook` and `%graph-pull-hook`.
357−`%graph-pull-hook` is responsible for asking other `%graph-push-hook`s for graph data
357+`%graph-pull-hook` is responsible for asking other `%graph-push-hook`s for graph data
358by trying to initiate a subscription on the host ship's `%graph-push-hook`, which the host only allows if they have permissions.
358by trying to initiate a subscription on the host ship's `%graph-push-hook`, which the host only allows if they have permissions.
359When it succeeds, `%graph-push-hook` then sends out all `graph-updates` to those subscribers who need to hear about it.
359When it succeeds, `%graph-push-hook` then sends out all `graph-updates` to those subscribers who need to hear about it.
360`%graph-pull-hook` then merges in graph updates it hears into the local `%graph-store`.
360`%graph-pull-hook` then merges in graph updates it hears into the local `%graph-store`.
content/docs/userspace/graph-store/validator-walkthrough.md+38−49
@@ -6,33 +6,32 @@ template = "doc.html"
6insert_anchor_links = "right"
6insert_anchor_links = "right"
7+++
7+++
8
8
9−
10## Schema and Permissioning Implementation
9## Schema and Permissioning Implementation
11−In this section, we will analyze various applications and see how they implement their schema and permissions.
12
10
11+In this section, we will analyze various applications and see how they implement their schema and permissions.
13
12
14### Current State of Permissioning
13### Current State of Permissioning
14+
15Please note that as it stands today, the current permissioning system is likely subject to change. It is by no means the only manner in which to set up permissionings. For many applications, writing a small and bespoke permissioning library may be suitable as an alternative to the `graph-push-hook` permissioning scheme which is what will be covered in the following examples.
15Please note that as it stands today, the current permissioning system is likely subject to change. It is by no means the only manner in which to set up permissionings. For many applications, writing a small and bespoke permissioning library may be suitable as an alternative to the `graph-push-hook` permissioning scheme which is what will be covered in the following examples.
16
16
17Also, please be aware that the current set of applications use a special type known as `vip-metadata`, which stands for "variation in permission".
17Also, please be aware that the current set of applications use a special type known as `vip-metadata`, which stands for "variation in permission".
18It is extra metadata attached to a post that is available to the permissioning arms that is mainly used to specify whether reader comments are enabled or disabled.
18It is extra metadata attached to a post that is available to the permissioning arms that is mainly used to specify whether reader comments are enabled or disabled.
19Here's the source if you want to explore: [`sur/metadata-store.hoon#L20-L30`](https://github.com/urbit/urbit/blob/ac096d85ae847fcfe8786b51039c92c69abc006e/pkg/arvo/sur/metadata-store.hoon#L20-L30)
19Here's the source if you want to explore: [`sur/metadata-store.hoon#L20-L30`](https://github.com/urbit/urbit/blob/ac096d85ae847fcfe8786b51039c92c69abc006e/pkg/arvo/sur/metadata-store.hoon#L20-L30)
20
20
21−
22### Chat
21### Chat
22+
23#### Schema
23#### Schema
24+
24Here's what the schema of chat looks like:
25Here's what the schema of chat looks like:
25
26
26−<p align="center">
27− <img src="https://media.urbit.org/docs/userspace/graph-store/7_chat_schema_diagram.png"/>
27+![Chat Schema Diagram](https://media.urbit.org/docs/userspace/graph-store/7_chat_schema_diagram.svg)
28−</p>
29
28
30A chat is a flat graph, where all chat messages are nodes appended to the root of the graph.
29A chat is a flat graph, where all chat messages are nodes appended to the root of the graph.
31The graph represents a chat channel and contains all chat messages in order. A chat message is a child node of the root graph.
30The graph represents a chat channel and contains all chat messages in order. A chat message is a child node of the root graph.
32
31
33−
34Here's the definition of the schema in the chat validator mark:
32Here's the definition of the schema in the chat validator mark:
35File: [`mar/graph/validator/chat.hoon`](https://github.com/urbit/urbit/blob/fbd85abf4e41d580654606a6defb764f6a97256d/pkg/arvo/mar/graph/validator/chat.hoon#L33-L40)
33File: [`mar/graph/validator/chat.hoon`](https://github.com/urbit/urbit/blob/fbd85abf4e41d580654606a6defb764f6a97256d/pkg/arvo/mar/graph/validator/chat.hoon#L33-L40)
34+
36```hoon
35```hoon
37++ grab
36++ grab
38 |%
37 |%
@@ -46,6 +45,7 @@ File: [`mar/graph/validator/chat.hoon`](https://github.com/urbit/urbit/blob/fbd8
46```
45```
47
46
48Here are the steps:
47Here are the steps:
48+
491. Given a noun (we expect an indexed-post)
491. Given a noun (we expect an indexed-post)
501. Try to coerce p to an indexed-post, crash if it doesn't cast
501. Try to coerce p to an indexed-post, crash if it doesn't cast
511. Assert that the index of the post of the indexed post is only a single atom, i.e., that it is only nested one level deep
511. Assert that the index of the post of the indexed post is only a single atom, i.e., that it is only nested one level deep
@@ -57,13 +57,12 @@ Since the schema of the chat application is simple enough, it has no need for st
57
57
58#### Permissioning
58#### Permissioning
59
59
60−<p align="center">
61− <img src="https://media.urbit.org/docs/userspace/graph-store/8_chat_permissions_diagram.png"/>
60+![Chat Permissions Diagram](https://media.urbit.org/docs/userspace/graph-store/8_chat_permissions_diagram.svg)
62−</p>
63
61
64Let's take a look at the permissions table in the diagram.
62Let's take a look at the permissions table in the diagram.
65
63
66Chat Message `[@ ~]`
64Chat Message `[@ ~]`
65+
67- Add Privileges
66- Add Privileges
68 - Admins and Writers have `%yes` add permissions for all nodes at the top level, meaning that they have the ability to post chat messages, even if they did not create the chat channel
67 - Admins and Writers have `%yes` add permissions for all nodes at the top level, meaning that they have the ability to post chat messages, even if they did not create the chat channel
69 - Readers have `%no` add privileges for any nodes at the root level, so they do not have the ability to post chat messages
68 - Readers have `%no` add privileges for any nodes at the root level, so they do not have the ability to post chat messages
@@ -77,6 +76,7 @@ For example, it wouldn't make sense to give readers `%self`, because they do not
77Let's see how this permissioning system is implemented in the validator code.
76Let's see how this permissioning system is implemented in the validator code.
78
77
79Here is the `grow` arm of [`mar/validator/chat.hoon`](https://github.com/urbit/urbit/blob/fbd85abf4e41d580654606a6defb764f6a97256d/pkg/arvo/mar/graph/validator/chat.hoon#L7-L20)
78Here is the `grow` arm of [`mar/validator/chat.hoon`](https://github.com/urbit/urbit/blob/fbd85abf4e41d580654606a6defb764f6a97256d/pkg/arvo/mar/graph/validator/chat.hoon#L7-L20)
79+
80```hoon
80```hoon
81|_ i=indexed-post :: A
81|_ i=indexed-post :: A
82++ grow
82++ grow
@@ -100,13 +100,13 @@ Here is the `grow` arm of [`mar/validator/chat.hoon`](https://github.com/urbit/u
100In line A, we accept an `indexed-post` that is used in the rest of the `grow` arm.
100In line A, we accept an `indexed-post` that is used in the rest of the `grow` arm.
101
101
102`graph-permissions-add`
102`graph-permissions-add`
103+
1031. Accept a noun `vip` of type `vip-metadata`
1041. Accept a noun `vip` of type `vip-metadata`
1042. Switch on the index of the post found in `i`, crashing if no successful matches occur
1052. Switch on the index of the post found in `i`, crashing if no successful matches occur
1053. If the index is nested one level deep
1063. If the index is nested one level deep
1064. Return a `permissions` noun defined as: [admin: %yes, writer: %yes, reader: %no]
1074. Return a `permissions` noun defined as: [admin: %yes, writer: %yes, reader: %no]
107
108
108−
109− `graph-permissions-remove`
109+ `graph-permissions-remove`
110
110
1115. Accept a noun `vip` of type vip-metadata
1115. Accept a noun `vip` of type vip-metadata
1126. Switch on the index, crashing if no successful matches occur
1126. Switch on the index, crashing if no successful matches occur
@@ -115,23 +115,21 @@ In line A, we accept an `indexed-post` that is used in the rest of the `grow` ar
115
115
116In this example, a switch statement is used to determine the `permissions` values based on the index of the post.
116In this example, a switch statement is used to determine the `permissions` values based on the index of the post.
117
117
118−
119### Links
118### Links
119+
120#### Schema
120#### Schema
121
121
122−<p align="center">
123− <img src="https://media.urbit.org/docs/userspace/graph-store/9_link_schema_diagram.png"/>
122+![Link Schema Diagram](https://media.urbit.org/docs/userspace/graph-store/9_link_schema_diagram.svg)
124−</p>
125
123
126The root graph represents the whole Links collection. Every Links entry is a child node of this graph. Every Links entry is made up of:
124The root graph represents the whole Links collection. Every Links entry is a child node of this graph. Every Links entry is made up of:
125+
127- The link and its description
126- The link and its description
128- A comments section
127- A comments section
129
128
130−
131The comments section holds all individual comment nodes, but comments are not simple leaf nodes. An individual comment is actually a structural node that acts as a revision container, storing the comment's full edit history by storing each edit as a child node. The front-end is responsible for properly displaying the latest revision of the comment.
129The comments section holds all individual comment nodes, but comments are not simple leaf nodes. An individual comment is actually a structural node that acts as a revision container, storing the comment's full edit history by storing each edit as a child node. The front-end is responsible for properly displaying the latest revision of the comment.
132
130
133−
134Here's the validator, located at [`mar/graph/validator/link.hoon`](https://github.com/urbit/urbit/blob/fbd85abf4e41d580654606a6defb764f6a97256d/pkg/arvo/mar/graph/validator/link.hoon#L49-L73):
131Here's the validator, located at [`mar/graph/validator/link.hoon`](https://github.com/urbit/urbit/blob/fbd85abf4e41d580654606a6defb764f6a97256d/pkg/arvo/mar/graph/validator/link.hoon#L49-L73):
132+
135```hoon
133```hoon
136++ grab
134++ grab
137 |%
135 |%
@@ -160,7 +158,6 @@ Here's the validator, located at [`mar/graph/validator/link.hoon`](https://githu
160 --
158 --
161```
159```
162
160
163−
164<ol>
161<ol>
165 <li>Get the post as a noun</li>
162 <li>Get the post as a noun</li>
166 <li>Force cast to indexed post</li>
163 <li>Force cast to indexed post</li>
@@ -181,22 +178,17 @@ Here's the validator, located at [`mar/graph/validator/link.hoon`](https://githu
181 </li>
178 </li>
182</ol>
179</ol>
183
180
184−
185It is important to note that you cannot directly edit the url or link afterwards, only the whole link entry itself. This is because you can only add or remove nodes to a graph, not modify them. Comments, however, can be “edited”. This is possible by using a technique called a revision container. Instead of having a single leaf node holding the comment text in its contents, a node with empty contents is created. All revisions of the comment are added as children to this note, and the frontend simply shows the most recent one only.
181It is important to note that you cannot directly edit the url or link afterwards, only the whole link entry itself. This is because you can only add or remove nodes to a graph, not modify them. Comments, however, can be “edited”. This is possible by using a technique called a revision container. Instead of having a single leaf node holding the comment text in its contents, a node with empty contents is created. All revisions of the comment are added as children to this note, and the frontend simply shows the most recent one only.
186
182
187#### Permissioning
183#### Permissioning
188
184
189−<p align="center">
190− <img src="https://media.urbit.org/docs/userspace/graph-store/10_links_permissions_diagram_a.png"/>
185+![Links Permissions Diagram A](https://media.urbit.org/docs/userspace/graph-store/10_links_permissions_diagram_a.svg)
191−</p>
192
186
193−<p align="center">
194− <img src="https://media.urbit.org/docs/userspace/graph-store/11_links_permissions_diagram_b.png"/>
187+![Links Permissions Diagram B](https://media.urbit.org/docs/userspace/graph-store/11_links_permissions_diagram_b.svg)
195−</p>
196
188
197Let's analyze the permissions structure.
189Let's analyze the permissions structure.
198
190
199−**TODO** *stubbed out awaiting potential changes in source*
191+**TODO** _stubbed out awaiting potential changes in source_
200
192
201Here's how it is implemented [(source)](https://github.com/urbit/urbit/blob/master/pkg/arvo/mar/graph/validator/link.hoon#L2-L27):
193Here's how it is implemented [(source)](https://github.com/urbit/urbit/blob/master/pkg/arvo/mar/graph/validator/link.hoon#L2-L27):
202
194
@@ -222,13 +214,14 @@ Here's how it is implemented [(source)](https://github.com/urbit/urbit/blob/mast
222 ?=(%reader-comments vip)
214 ?=(%reader-comments vip)
223 ?+ index.p.i !! :: 6
215 ?+ index.p.i !! :: 6
224 [@ ~] [%yes %self %self] :: 6a
216 [@ ~] [%yes %self %self] :: 6a
225− [@ @ ~] [%yes %self %self] ::
217+ [@ @ ~] [%yes %self %self] ::
226− [@ @ @ ~] [%yes %self %self] ::
218+ [@ @ @ ~] [%yes %self %self] ::
227 ==
219 ==
228 ::
220 ::
229```
221```
230
222
231`graph-permissions-add`
223`graph-permissions-add`
224+
232<ol>
225<ol>
233 <li>Accept a noun <code>vip</code> of type vip-metadata
226 <li>Accept a noun <code>vip</code> of type vip-metadata
234 <ul>
227 <ul>
@@ -259,8 +252,8 @@ Here's how it is implemented [(source)](https://github.com/urbit/urbit/blob/mast
259 </li>
252 </li>
260</ol>
253</ol>
261
254
262−
263`graph-permissions-remove`
255`graph-permissions-remove`
256+
264<ol>
257<ol>
265 <li>Accept a noun <code>vip</code> of type vip-metadata</li>
258 <li>Accept a noun <code>vip</code> of type vip-metadata</li>
266 <li>Declare a variable <code>reader</code>, a flag which is true if reader comments are enabled, false otherwise</li>
259 <li>Declare a variable <code>reader</code>, a flag which is true if reader comments are enabled, false otherwise</li>
@@ -274,19 +267,16 @@ Here's how it is implemented [(source)](https://github.com/urbit/urbit/blob/mast
274 </li>
267 </li>
275</ol>
268</ol>
276
269
277−
278−
279### Publish
270### Publish
280
271
281#### Schema
272#### Schema
282
273
283−<p align="center">
284− <img src="https://media.urbit.org/docs/userspace/graph-store/12_publish_schema_diagram.png"/>
274+![Publish Schema Diagram](https://media.urbit.org/docs/userspace/graph-store/12_publish_schema_diagram.svg)
285−</p>
286
275
287Here, a notebook, which is a collection of blog posts (called notes), is represented by the root graph. All data associated with the blog post is represented by the top level node, which is the note itself along with the associated comments. One level deeper, we see two container structures. The first one is the post revision container; it holds the edit history of your blog post. Every child node of this corresponds to the actual title and text of your blog post. The second one is the comments container. This represents the comment section of your blog post. Every child node of this is not a comment, but a comment revision container, which, as before, contains the edit history of your comment.
276Here, a notebook, which is a collection of blog posts (called notes), is represented by the root graph. All data associated with the blog post is represented by the top level node, which is the note itself along with the associated comments. One level deeper, we see two container structures. The first one is the post revision container; it holds the edit history of your blog post. Every child node of this corresponds to the actual title and text of your blog post. The second one is the comments container. This represents the comment section of your blog post. Every child node of this is not a comment, but a comment revision container, which, as before, contains the edit history of your comment.
288
277
289Here's its validator, located at [`mar/graph/validator.hoon`](https://github.com/urbit/urbit/blob/master/pkg/arvo/mar/graph/validator/publish.hoon#L56-L97)
278Here's its validator, located at [`mar/graph/validator.hoon`](https://github.com/urbit/urbit/blob/master/pkg/arvo/mar/graph/validator/publish.hoon#L56-L97)
279+
290```hoon
280```hoon
291 ++ noun
281 ++ noun
292 |= p=* :: 1
282 |= p=* :: 1
@@ -330,7 +320,6 @@ Here's its validator, located at [`mar/graph/validator.hoon`](https://github.com
330
320
331Walkthrough
321Walkthrough
332
322
333−
334<ol>
323<ol>
335 <li>Get the post as a noun</li>
324 <li>Get the post as a noun</li>
336 <li>Force cast to indexed post</li>
325 <li>Force cast to indexed post</li>
@@ -366,17 +355,13 @@ Notably, the revision container for the blog post itself allows the post to be e
366
355
367#### Permissioning
356#### Permissioning
368
357
369−<p align="center">
370− <img src="https://media.urbit.org/docs/userspace/graph-store/13_publish_permissions_diagram_a.png"/>
358+![Publish Permissions Diagram A](https://media.urbit.org/docs/userspace/graph-store/13_publish_permissions_diagram_a.svg)
371−</p>
372
359
373−<p align="center">
374− <img src="https://media.urbit.org/docs/userspace/graph-store/14_publish_permissions_diagram_b.png"/>
360+![Publish Permissions Diagram B](https://media.urbit.org/docs/userspace/graph-store/14_publish_permissions_diagram_b.svg)
375−</p>
376
361
377Let's take a look at the permissioning structure for Publish.
362Let's take a look at the permissioning structure for Publish.
378
363
379−**TODO** *stubbed out awaiting potential changes in source*
364+**TODO** _stubbed out awaiting potential changes in source_
380
365
381[(source)](https://github.com/urbit/urbit/blob/fbd85abf4e41d580654606a6defb764f6a97256d/pkg/arvo/mar/graph/validator/publish.hoon#L6-L24)
366[(source)](https://github.com/urbit/urbit/blob/fbd85abf4e41d580654606a6defb764f6a97256d/pkg/arvo/mar/graph/validator/publish.hoon#L6-L24)
382
367
@@ -399,8 +384,8 @@ Let's take a look at the permissioning structure for Publish.
399 ?+ index.p.i !! :: 4
384 ?+ index.p.i !! :: 4
400 [@ ~] [%yes %self %self] :: 4a
385 [@ ~] [%yes %self %self] :: 4a
401 [@ %1 @ @ ~] [%yes %self %self] ::
386 [@ %1 @ @ ~] [%yes %self %self] ::
402− [@ %2 @ ~] [%yes %self %self] ::
387+ [@ %2 @ ~] [%yes %self %self] ::
403− [@ %2 @ @ ~] [%yes %self %self] ::
388+ [@ %2 @ @ ~] [%yes %self %self] ::
404 ==
389 ==
405::
390::
406```
391```
@@ -440,8 +425,8 @@ Let's take a look at the permissioning structure for Publish.
440 </li>
425 </li>
441</ol>
426</ol>
442
427
443−
444`graph-permissions-remove`
428`graph-permissions-remove`
429+
445<ol>
430<ol>
446 <li>Accept a noun <code>vip</code> of type <code>vip-metadata</code></li>
431 <li>Accept a noun <code>vip</code> of type <code>vip-metadata</code></li>
447 <li>Declare a variable <code>reader</code>, a flag which is true if reader comments are enabled, false otherwise</li>
432 <li>Declare a variable <code>reader</code>, a flag which is true if reader comments are enabled, false otherwise</li>
@@ -456,9 +441,13 @@ Let's take a look at the permissioning structure for Publish.
456</ol>
441</ol>
457
442
458## General Patterns and Best Practices
443## General Patterns and Best Practices
444+
459### General Patterns
445### General Patterns
446+
460#### Schemas
447#### Schemas
448+
461The general pattern for enforcing a schema in a validator is to:
449The general pattern for enforcing a schema in a validator is to:
450+
4621. Cast the incoming data as an `indexed-post`
4511. Cast the incoming data as an `indexed-post`
4631. Switch on the index, matching by its depth and structure
4521. Switch on the index, matching by its depth and structure
4641. Validate the structure of the contents of the post based on what we expect to see at that level of nesting. This logic can definitely be more involved than simply presence or absence of data.
4531. Validate the structure of the contents of the post based on what we expect to see at that level of nesting. This logic can definitely be more involved than simply presence or absence of data.
@@ -467,11 +456,12 @@ When designing your schema, it may help to decide first what data the user will
467
456
468In general, validators can be as robust and expressive as desired, because the mark system already sets proper limitations of what you can and cannot do, with the main restriction being no side effects can be produced by a mark.
457In general, validators can be as robust and expressive as desired, because the mark system already sets proper limitations of what you can and cannot do, with the main restriction being no side effects can be produced by a mark.
469
458
470−
471#### Permissions
459#### Permissions
460+
472In general, you want to first have your schema finalized, then at every node ask the question: who should be able to modify (add/remove) this node, and its children if present in your schema. You may find that you don't need to set permission for every single type of node afterwards, although being thorough can help to find bugs in permissioning early on. Writing out the permissions in plain words and bullet points, sketching them out in the form of a table, then splitting it up into the code can also make the design process easier.
461In general, you want to first have your schema finalized, then at every node ask the question: who should be able to modify (add/remove) this node, and its children if present in your schema. You may find that you don't need to set permission for every single type of node afterwards, although being thorough can help to find bugs in permissioning early on. Writing out the permissions in plain words and bullet points, sketching them out in the form of a table, then splitting it up into the code can also make the design process easier.
473
462
474### Earth/Mars Interface Details
463### Earth/Mars Interface Details
464+
475There are a few general ways to talk to a Graph Store gall agent. You can either interact with the agent in the form of pokes/scries/spiders either directly from the dojo, or through HTTP requests via Eyre.
465There are a few general ways to talk to a Graph Store gall agent. You can either interact with the agent in the form of pokes/scries/spiders either directly from the dojo, or through HTTP requests via Eyre.
476
466
477- All graph store applications are going to have a mark, which are applied to data going in or coming out
467- All graph store applications are going to have a mark, which are applied to data going in or coming out
@@ -479,9 +469,8 @@ There are a few general ways to talk to a Graph Store gall agent. You can either
479- In the case of data going in, you pass in a `marked-graph` which the Graph Store agent uses to validate the whole `graph` with. In the case of adding a node to a graph, the node will simply be checked for validity using the existing mark since the mark is already set on a per-graph basis
469- In the case of data going in, you pass in a `marked-graph` which the Graph Store agent uses to validate the whole `graph` with. In the case of adding a node to a graph, the node will simply be checked for validity using the existing mark since the mark is already set on a per-graph basis
480- In the case of data coming out, Eyre forcibly tries to convert the hoon noun into json, and silently fails if no json conversion exists. This process is handled by Graph Store under the hood because all graphs have a well-defined en-json/de-json format, so you never have to worry about making your own de/serialization arms.
470- In the case of data coming out, Eyre forcibly tries to convert the hoon noun into json, and silently fails if no json conversion exists. This process is handled by Graph Store under the hood because all graphs have a well-defined en-json/de-json format, so you never have to worry about making your own de/serialization arms.
481
471
482−
483Code References
472Code References
473+
484- [`interface/src/logic/api/base.ts#L62`](https://github.com/urbit/urbit/blob/master/pkg/interface/src/logic/api/base.ts#L62)
474- [`interface/src/logic/api/base.ts#L62`](https://github.com/urbit/urbit/blob/master/pkg/interface/src/logic/api/base.ts#L62)
485- [`mar/graph/update.hoon`](https://github.com/urbit/urbit/blob/e2ad6e3e9219c8bfad62f27f05c7cac94c9effa8/pkg/arvo/mar/graph/update.hoon)
475- [`mar/graph/update.hoon`](https://github.com/urbit/urbit/blob/e2ad6e3e9219c8bfad62f27f05c7cac94c9effa8/pkg/arvo/mar/graph/update.hoon)
486- [`sys/vane/eyre.hoon#L1617-L1625`](https://github.com/urbit/urbit/blob/ac096d85ae847fcfe8786b51039c92c69abc006e/pkg/arvo/sys/vane/eyre.hoon#L1617-L1625) shows how Eyre applies marks
476- [`sys/vane/eyre.hoon#L1617-L1625`](https://github.com/urbit/urbit/blob/ac096d85ae847fcfe8786b51039c92c69abc006e/pkg/arvo/sys/vane/eyre.hoon#L1617-L1625) shows how Eyre applies marks
487−