@@ -0,0 +1,195 @@
7+
9+The architecture of Landscape’s userspace application suite has gone through a
10+number of overhauls in the past few years, and each iteration has gotten closer
11+to a point where Urbit’s userspace can truly perform as a next-generation social
12+suite built entirely on distributed networking and individual-owned personal
15+As of this year, this application suite has arrived at a point where we’re
16+confident both in how all the parts fit together, and confident in the
20+## What is Landscape Intended to Be?
22+Landscape is a single suite of userspace applications built to run on top of
23+Urbit. Landscape is maintained by [Tlon](https://tlon.io), a for-profit corporation that helps
24+research Urbit. Landscape is one of many possible application suites for Urbit,
25+and we hope many others emerge that build on top of the Arvo kernel. We plan on
26+making Landscape itself more extensible for user-developers in late 2021.
28+Landscape is specifically a social suite of applications, meant to enable
29+communication and socializing in many forms.
32+## What is Landscape technically composed of?
34+Landscape is composed of two primary parts: its backend, which runs as a suite of userspace applications (also known as Gall agents), and its frontend interface, which runs as a single-page web application. Both the backend and the frontend may be decomposed into their constituent parts for further understanding.
39+The Landscape backend is implemented as a collection of long-running
40+microservices known as [Gall agents](@/docs/arvo/gall/gall.md). They can be divided into the following,
41+though this is a simplification:
43+- **Graph**: handles storing messages / posts in a non-relational database
44+- **Groups**: organizes people into groups and roles and handles permissioning
45+- **Metadata**: a database join between graphs and groups, it also provides
46+ titles and descriptions for graphs and groups
47+- **Contacts**: handles nicknames, profile pictures, and ship-related metadata
48+- **Invites**: a generic inviting subsystem that is used for joining graphs or groups
49+- **Hark**: a notification subsystem for keeping track of read state and
52+Each of these components are built out using a few microservices that handle
53+more specific responsibilities. These responsibilities can be subdivided into
54+two main categories: [stores](#stores) and [hooks](#hooks). To simply describe
55+the separation of responsibilities, stores are dumb databases (models in MVC)
56+and hooks are for processing data (controllers in MVC).
61+Concisely defined, a store is a dumb database. It does not send outgoing pokes,
62+watches, or peeks, except in an `+on-load` to migrate its state. It does store
63+permanent and/or temporary state, allows incoming peeks/watches to read that
64+data, and allows pokes to modify that data. A store may only accept local reads
65+and writes, not remote ones. It may or may not interact with various kernel
66+modules. Examples include:
67+[graph-store](https://github.com/urbit/urbit/blob/ac096d85ae847fcfe8786b51039c92c69abc006e/pkg/arvo/app/graph-store.hoon),
68+[group-store](https://github.com/urbit/urbit/blob/ac096d85ae847fcfe8786b51039c92c69abc006e/pkg/arvo/app/group-store.hoon),
69+[metadata-store](https://github.com/urbit/urbit/blob/ac096d85ae847fcfe8786b51039c92c69abc006e/pkg/arvo/app/metadata-store.hoon),
70+[contact-store](https://github.com/urbit/urbit/blob/ac096d85ae847fcfe8786b51039c92c69abc006e/pkg/arvo/app/contact-store.hoon),
72+[invite-store](https://github.com/urbit/urbit/blob/ac096d85ae847fcfe8786b51039c92c69abc006e/pkg/arvo/app/invite-store.hoon).
77+A hook is a more loosely-defined agent that performs business logic. It should
78+only keep track of a minimal amount of state (*e.g.* active subscriptions). Hooks
79+are used for a variety of purposes in the system, but there are a few important
80+hook patterns to be aware of:
84+A pull-hook syncs data from a remote resource down to a local resource. There is
86+[pull-hook](https://github.com/urbit/urbit/blob/master/pkg/arvo/lib/pull-hook.hoon)
87+library that drastically simplifies the implementation of such a hook, and is
88+the defacto standard for how to sync down remote data to your ship.
92+A push-hook allows remote ships to subscribe to and sync down the information
93+from a local resource. There is a [push-hook
94+library](https://github.com/urbit/urbit/blob/ac096d85ae847fcfe8786b51039c92c69abc006e/pkg/arvo/lib/push-hook.hoon)
95+that drastically simplifies the implementation of such a hook, and is the
96+defacto standard for how to make local data available to remote ships.
100+The observe-hook subscribes to data coming in from another agent, and starts up
101+a thread of computation every time a subscription update from that agent is
106+The poke-proxy-hook conditionally forwards a poke from a foreign ship to a store
107+on the local ship if the foreign ship has permission to do so.
114+Groups are the core building block of data permissioning within Landscape. A
115+group is made up of the following fields:
119+ $: members=(set ship)
126+- `members` is a set of ships that are at present in the group
127+- `tags` are strings that may define additional permissions or roles within the
129+- The `policy` defines whether a group is open to new members, is invite-only, or
130+ has some other scheme
131+- `hidden` is a boolean flag that determines whether the group’s lifecycle is
132+ attached to a single external resource (such as a chat DM, which when the DM
133+ is deleted, the group is deleted too), or whether it has an independent life
134+ of its own. This flag also determines whether the group should show up in
135+ interfaces as something that may be managed and edited.
137+The `%group-store` holds a map of these groups and allows subscriptions to their
138+data. The group-store may be accessed from foreign ships through the use of the
139+`%group-pull-hook` and `%group-push-hook`. Groups may be joined either by
140+manually discovering and pasting in a group name into the “join group” dialogue
141+in the interface for an open group, or by accepting an invite to an invite-only
142+group. When a group is deleted, all data related to it is deleted or archived as
147+Graphs are the core place where we store social user-generated content: chat
148+messages, social network posts, blog posts, links, and eventually multimedia.
149+Graph store is built to be flexible enough to support many different types of
150+“apps” built on top of it, whether you want to have a forum with some friends, a
151+Pinterest equivalent, a more private version of Facebook, a decentralized
152+Reddit, or an even more distributed version of Mastodon. You can read more about
153+graph-store by [viewing the
154+source](https://github.com/urbit/urbit/blob/ac096d85ae847fcfe8786b51039c92c69abc006e/pkg/arvo/app/graph-store.hoon)
155+or reading our [API Reference](@/docs/landscape/reference/graph-store.md) documentation.
157+The `%graph-store` may be accessed from foreign ships through the use of the
158+`%graph-pull-hook` and `%graph-push-hook`.
162+Metadata is stored in the `%metadata-store`, and is where we store metadata
163+about resources (ex: graphs or groups). We store their display name,
164+description, a color, and the date they were added. We also store what group the
165+resource is associated with, what app the resource is associated with, and what
166+module (display mode) the resource should be used with.
168+Metadata within the broader context of the userspace application suite can best
169+be thought of as a database join between the `%group-store` and the
170+`%graph-store`, as it provides bidirectional indices for querying all of the
171+graphs that a group has, or which group a particular graph is associated with.
176+Contacts are your address book. Individual ships (people) you talk to may have a
177+ nickname, a profile picture, or a colored sigil background that helps you
178+ identify them in groups, chatrooms, blogs, and collections.
183+Invites is a simple subsystem that allows you to send all the details of a given
184+resource (*e.g.* graph or group) to some other ship so that they may join it if
185+they desire to. Invite acceptance is handled with threads that listen to the
186+`%invite-store` using the `%observe-hook` and invite sending is handled with the
187+`%invite-hook`, which allows any ship to send you an invite without any
188+permissions involved.
193+Hark is a generic notification and unread-tracking subsystem that currently
194+keeps track of all unread functionality for the system. The `%hark-graph-hook`
195+sends data about `%graph-store` events to `%hark-store`.