on master help sign in
Merge branch 'master' of github.com:urbit/urbit.org
commitf87acde7a369d4a5a0369f6949756468be2fcfc9 authorGavin Atkinson <gvnatknsn@protonmail.com> dateThu 29 Jul 2021, 12:11 (5 years ago) parent1e684f4d8a0565
18 files changed+344−282
components/ContentArea.js+23−1 components/Header.js+18−2 components/TableOfContents.js+1−1 content/blog/a-topiary.md+37 content/docs/arvo/eyre/_index.md+4−4 content/docs/arvo/eyre/data-types.md+32−33 content/docs/arvo/eyre/examples.md+29−41 content/docs/arvo/eyre/external-api-ref.md+35−57 content/docs/arvo/eyre/eyre.md+20−20 content/docs/arvo/eyre/scry.md+31−49 content/docs/arvo/eyre/tasks.md+43−60 content/grants/urbit-http-api-for-python.md+43 lib/rss.js+4−6 pages/community/[[...slug]].js+1 pages/docs/[[...slug]].js+2−3 pages/getting-started/[[...slug]].js+1−2 pages/understanding-urbit/[[...slug]].js+19−1 pages/using/[[...slug]].js+1−2
components/ContentArea.js+23−1
@@ -1,6 +1,25 @@
11import Section from "./Section";
2+import { useState, useEffect } from "react";
3+import { TableOfContents } from "./TableOfContents";
24
35export default function ContentArea(props) {
6+ const [shortcut, setShortcut] = useState("");
7+
8+ const detectOS = () => {
9+ const agent = window.navigator.appVersion;
10+ if (agent.includes("Win")) {
11+ return "Ctrl+K";
12+ } else if (agent.includes("Mac")) {
13+ return "⌘K";
14+ } else if (agent.includes("Linux")) {
15+ return "Ctrl+K";
16+ }
17+ };
18+
19+ useEffect(() => {
20+ setShortcut(detectOS());
21+ }, []);
22+
423 return (
524 <div className="w-full min-w-0 flex flex-col">
625 <div className="px-4 md:px-12 lg:px-24 pb-24 pt-8 md:pt-10 lg:pt-16 flex flex-col w-full max-h-screen h-screen overflow-y-scroll">
@@ -14,7 +33,7 @@ export default function ContentArea(props) {
1433 }}
1534 className="button-sm bg-wall text-gray"
1635 >
17− Search<div className="ml-4 text-lightGray">⌘K</div>
36+ Search<div className="ml-4 text-lightGray">{shortcut}</div>
1837 </button>
1938 </div>
2039 </div>
@@ -32,6 +51,9 @@ export default function ContentArea(props) {
3251 <div className="pb-32" />
3352 </div>
3453 )}
54+ <TableOfContents
55+ key={props.params.slug?.join("/") || Math.random()}
56+ />
3557 </div>
3658 </div>
3759 </div>
components/Header.js+18−2
@@ -1,6 +1,6 @@
11import Link from "next/link";
22import { useRouter } from "next/router";
3−import { useState } from "react";
3+import { useState, useEffect } from "react";
44import classnames from "classnames";
55import path from "path";
66import MenuTray from "../components/MenuTray";
@@ -24,6 +24,7 @@ function ActiveLink({ children, href, className, currentPath }) {
2424
2525export default function Header(props) {
2626 const [isOpen, setTray] = useState(false);
27+ const [shortcut, setShortcut] = useState("");
2728
2829 const currentPath = useRouter().asPath;
2930
@@ -31,6 +32,21 @@ export default function Header(props) {
3132
3233 const firstCrumb = currentPath.split("/")[1];
3334
35+ const detectOS = () => {
36+ const agent = window.navigator.appVersion;
37+ if (agent.includes("Win")) {
38+ return "Ctrl+K";
39+ } else if (agent.includes("Mac")) {
40+ return "⌘K";
41+ } else if (agent.includes("Linux")) {
42+ return "Ctrl+K";
43+ }
44+ };
45+
46+ useEffect(() => {
47+ setShortcut(detectOS());
48+ }, []);
49+
3450 return (
3551 <header className="w-full px-4 md:px-8 md:w-10/12 flex flex-row justify-between items-center pt-8 md:pt-10 lg:pt-12 pb-10 md:pb-12 lg:pb-24">
3652 <div>
@@ -85,7 +101,7 @@ export default function Header(props) {
85101 className="bg-wall text-gray flex px-4 py-1 rounded-lg type-ui"
86102 >
87103 <div>Search</div>
88− <div className="ml-4 text-lightGray">⌘K</div>
104+ <div className="ml-4 text-lightGray">{shortcut}</div>
89105 </button>
90106 </nav>
91107
components/TableOfContents.js+1−1
@@ -8,7 +8,7 @@ export const TableOfContents = ({ staticPosition, noh3s }) => {
88 <nav
99 className={
1010 (staticPosition ? "static" : "sticky") +
11− " min-h-0 overflow-y-auto w-52 flex-shrink-0 pb-24 hidden lg:block"
11+ " min-h-0 overflow-y-auto w-52 flex-shrink-0 pb-24 hidden lg:block pl-4"
1212 }
1313 style={{ top: "8rem", height: "calc(100vh - 16rem)" }}
1414 >
content/blog/a-topiary.mdnew file+37
@@ -0,0 +1,37 @@
1++++
2+title = "A Topiary: Hypertext and Urbit"
3+date = 2021-06-14
4+description = "A brief history of hypertext and Urbit networking"
5+[extra]
6+author = "Reid Scoggin"
7+ship = "~sitful-hatred"
8+image = "https://media.urbit.org/site/posts/essays/treebranches.jpeg"
9++++
10+
11+![](https://media.urbit.org/site/posts/essays/treebranches.jpeg)
12+
13+> Under the trees of England I meditated on this lost and perhaps mythical labyrinth. I imagined it untouched and perfect on the secret summit of some mountain; I imagined it drowned under rice paddies or beneath the sea; I imagined it infinite, made not only of eight-sided pavilions and of twisting paths but also of rivers, provinces and kingdoms... I thought of a maze of mazes, of a sinuous, ever growing maze which would take in both past and future and would somehow involve the stars.
14+
15+-- _The Garden of Forking Paths_, Jorge Luis Borges
16+
17+The pre-technological world was already [networked](https://en.wikipedia.org/wiki/Indra%27s_net). No material object and no idea has ever stood alone—"no man is an island". Language itself is a network of associations shared between a group of people. The question of technology is: how do we bring our web of associations into the realm of computers? The legacy internet has focused on social networks almost exclusively—our mammalian brains readily took to this, we all love to [signal](https://conversationswithtyler.com/episodes/robin-hanson/). But before “social media” there was something called hypertext: a seemingly modest way to connect documents shared between computers.
18+
19+A footnote in a book used to require a library, locating the referenced book, and finding the cited page (which might have footnotes itself)! Hypertext allows one to traverse a network quickly and easily with just mouse clicks, making information accessible to those without the time and resources to hunt down physical artifacts. Urbit’s “%graph-store” is not the same as hypertext but it does bear some familial resemblances. Fundamentally, %graph-store is a data structure that can accommodate disparate data types within a single edifice. It is based on [graph databases](https://en.wikipedia.org/wiki/Graph_database) and recent implementations such as [GraphQL](https://graphql.org/). To understand this data structure it is worth diving into the origins of hypertext—the original linked network.
20+
21+The story of hypertext begins at the end of WWII with an article in _The Atlantic_ that proposed to extend the human mind via machine. Vannevar Bush had seen first-hand the explosion of electronics manufacturing and scientific knowledge, recognizing the great peril and opportunity of such a revolution. His [description](https://www.theatlantic.com/magazine/archive/1945/07/as-we-may-think/303881/) of the Memex presaged the technological world of today, envisioning a personal device that would allow the user to draw upon a vast library of information, and link documents together arbitrarily—what he called "associative indexing"—a deliberate recreation of how the mind connects thoughts.
22+
23+The 1960s saw the first implementations of these ideas. Ted Nelson's [writing](https://archive.org/details/SelectedPapers1977/page/n15/mode/2up) around _Project Xanadu_ elaborated this linking between documents into what Nelson called _hypertext_. Nelson imagined "a text arranged in a graph structure", centered around a corpus arranged in nonlinear sequence, manipulable by author or audience. The concept was first demonstrated in 1968, at Douglas Engelbart's 'Mother of all Demos', where a vision of computers as a collaborative social environment was revealed to the world. "[The Journal](https://www.dougengelbart.org/content/view/137/#7)", presented alongside other revolutionary demos, exhibited collaboratively edited documents with hyperlinked connections. Any time-travellers in the audience would have immediately recognized the first webpage. From here, the idea of a linked network of documents would be developed through successive phases of computing, from the mainframe to the PC.
24+
25+Experimentation with these ideas continued through the 1970s and 80s. A team directed by Andy Lippman at MIT extended the concept to threaded visual hypermedia with the _Aspen Movie Map_, a user-directed virtual tour of Aspen, Colorado. Hypertext and hypermedia gained a mass audience for the first time with HyperCard, a program that shipped with Mac computers. Users were able to collect or create '[stacks](https://archive.org/details/hypercardstacks)' of interlinked cards; a personal body of text, art, and knowledge could be accrued and modified, or shared with others—though not yet with native networking capabilities.
26+
27+With the World Wide Web, hypertext achieved escape velocity. Initially a one-man [project](http://info.cern.ch/hypertext/WWW/TheProject.html), the world wide web was similar to Bush’s vision of the Memex—a way to share, index, and connect information between individuals and groups. The web succeeded by utilizing the physical infrastructure already available: PCs with graphical interfaces, DNS, and the internet. Critically, its method of transmitting and traversing texts was a standardized protocol, allowing a free body of information to assemble atop the new infrastructure by anyone willing to learn the tools. A new frontier was cleared and cultivated with open standards, but it would gradually face enclosure.
28+
29+In the following decade, after the first wave of social networking sites had crested but before phones became the primary web clients, Twitter was launched. Originally an awkward bridge between SMS and the web, its design eventually coalesced around static identity, posts with chronological sorting, and interlinked post threads. These simple primitives spawned a vast corpus of information, a graph-of-graphs intertwined and overlapped, mapping an entire platonic world. Twitter is fundamentally constrained by its very nature: it is the walled garden of an advertising company. The financial incentives of the server operators demanded seizure of the commons and the replacement of standardized protocols with proprietary databases.
30+
31+As the first networked services withered, a new critique was implicitly articulated in the construction of a [new kind of abstract machine](https://moronlab.blogspot.com/2010/01/urbit-functional-programming-from.html). Urbit learned from the past: tightly defined protocols, baked-in cryptography, and decentralization were key. If power over the network was determined by those who ran the servers, then we would run the servers ourselves.
32+
33+Urbit is not fundamentally a hypertext system; it is a new kind of computer, designed to participate in a peer-to-peer network that rejects the client-server model. All Urbit software takes its networking model for granted, it is not an ad-hoc layering of mismatched abstractions. Fundamental design decisions determine the trajectory of the future.
34+
35+Early [implementations](https://en.wikipedia.org/wiki/Neo4j) of graph databases and projects like [RDF](https://en.wikipedia.org/wiki/Resource_Description_Framework) hit on the same core idea: linked data needs its own data structure. In 2020 Urbit OS adopted an application called %graph-store that made use of a new, native [data structure](https://docs.google.com/document/d/1-Gwfg442kV3cdfG7NnWPEf2TMa3uLUTAKkZD70ALZkE/edit) which would act as a database service for social applications. Chats, long-form text, and other types of data produced in the course of social computing now share the same tent, a single structure extensible to new types of content. Each item added to it is a node in a personal graph—a tree that grows branches as your computer communicates. These nodes can be linked arbitrarily to other graphs—Urbit's global immutable namespace grants both permanence and ownership and allows the graph’s branches to intertwine with others. Graphs can accommodate a variety of content, from simple text, to code and media yet to be conceived. You own your graph, and it is a record of your digital journey with others.
36+
37+Personal hypertext graphs are leaving behind proprietary platforms and gaining independence. Graphs until now have been used as tools of surveillance and marketing, but they are being reclaimed and sewn back into the network, each bound to the cryptographic identity of an individual, permanent computer. Where the map of your life was once splintered across a thousand systems and held in the custody of strangers, it is now possessed only by you and shared only as you see fit. On Urbit, an infinite forest of digital lives can take root, nesting their boughs and stalks.
content/docs/arvo/eyre/_index.md+4−4
@@ -14,18 +14,18 @@ An overview of Eyre and its capabilities.
1414
1515Details of Eyre's external API including the channel system's JSON API.
1616
17−## [Internal API Reference](@/docs/arvo/eyre/tasks.md)
17+## [Internal API Reference](/docs/arvo/eyre/tasks)
1818
1919The `task`s Eyre takes and the `gift`s it returns.
2020
21−## [Scry Reference](@/docs/arvo/eyre/scry.md)
21+## [Scry Reference](/docs/arvo/eyre/scry)
2222
2323The scry endpoints of Eyre.
2424
25−## [Data Types](@/docs/arvo/eyre/data-types.md)
25+## [Data Types](/docs/arvo/eyre/data-types)
2626
2727Reference documentation of the various data types used by Eyre.
2828
29−## [Examples](@/docs/arvo/eyre/examples.md)
29+## [Examples](/docs/arvo/eyre/examples)
3030
3131Practical examples of the different ways of using Eyre.
content/docs/arvo/eyre/data-types.md+32−33
@@ -4,16 +4,15 @@ weight = 5
44template = "doc.html"
55+++
66
7−# Introduction
8−
97This document describes the data types used by Eyre as defined in `/sys/lull.hoon`. It's separated into two sections:
108
11−- [Eyre](#eyre) - Eyre-specific data types.
12−- [HTTP](#http) - HTTP data types shared between Eyre and Iris.
9+[Eyre](#eyre) - Eyre-specific data types.
10+
11+[HTTP](#http) - HTTP data types shared between Eyre and Iris.
1312
14−# Eyre
13+## Eyre
1514
16−## `$origin`
15+### `$origin`
1716
1817```hoon
1918+$ origin @torigin
@@ -21,7 +20,7 @@ This document describes the data types used by Eyre as defined in `/sys/lull.hoo
2120
2221A single CORS origin as used in an HTTP Origin header and the [$cors-registry](#cors-registry).
2322
24−## `$cors-registry`
23+### `$cors-registry`
2524
2625```hoon
2726+$ cors-registry
@@ -33,7 +32,7 @@ A single CORS origin as used in an HTTP Origin header and the [$cors-registry](#
3332
3433CORS origins categorised by approval status. The `requests` `set` contains all [$origin](#origin)s Eyre has received in the headers of HTTP requests that have not been explicitly approved or rejected. The `approved` and `rejected` `set`s are those that have been explicitly approved or rejected.
3534
36−## `$outstanding-connection`
35+### `$outstanding-connection`
3736
3837```hoon
3938+$ outstanding-connection
@@ -46,15 +45,15 @@ CORS origins categorised by approval status. The `requests` `set` contains all [
4645
4746An HTTP connection that is currently open. The [$action](#action) is how it's being handled (e.g. by a Gall app, the channel system, etc). The [$inbound-request](#inbound-request) is the original request which opened the connection. The `response-header` contains the status code and headers. The `bytes-sent` is the total bytes sent so far in response.
4847
49−## `$authentication-state`
48+### `$authentication-state`
5049
5150```hoon
5251+$ authentication-state sessions=(map @uv session)
5352```
5453
55−This represents the authentication state of all sessions. It maps session cookies (without the `urbauth-<ship>=` prefix) to [$session](#session)s.
54+This represents the authentication state of all sessions. It maps session cookies (without the `urbauth-{SHIP}=` prefix) to [$session](#session)s.
5655
57−## `$session`
56+### `$session`
5857
5958```hoon
6059+$ session
@@ -65,7 +64,7 @@ This represents the authentication state of all sessions. It maps session cookie
6564
6665This represents server-side data about a session. The `expiry-time` is when the `session` expires and `channels` is the `set` of [$channel](#channel) names opened by the session.
6766
68−## `$channel-state`
67+### `$channel-state`
6968
7069```hoon
7170+$ channel-state
@@ -76,7 +75,7 @@ This represents server-side data about a session. The `expiry-time` is when the
7675
7776The state used by the channel system. The `session` is a `map` between channel names and [$channel](#channel)s and the `duct-to-key` `map`s `duct`s to `channel` names.
7877
79−## `$timer`
78+### `$timer`
8079
8180```hoon
8281+$ timer
@@ -87,7 +86,7 @@ The state used by the channel system. The `session` is a `map` between channel n
8786
8887A reference to a timer so it can be cancelled or updated. The `date` is when it will fire and the `duct` is what set the timer.
8988
90−## `$channel-event`
89+### `$channel-event`
9190
9291```hoon
9392+$ channel-event
@@ -100,7 +99,7 @@ A reference to a timer so it can be cancelled or updated. The `date` is when it
10099
101100An unacknowledged event in the channel system.
102101
103−## `$channel`
102+### `$channel`
104103
105104```hoon
106105+$ channel
@@ -116,7 +115,7 @@ An unacknowledged event in the channel system.
116115
117116This is the state of a particular channel in the channel system. The `state` is either the expiration time or the duct currently listening. The `next-id` is the next event ID to be used in the event stream. The `last-ack` is the date of the last client ack and is used for clog calculations in combination with `unacked`. The `events` queue contains all unacked events - `id` is the server-set event ID, `request-id` is the client-set request ID and the [$channel-event](#channel-event) is the event itself. The `unacked` `map` contains the unacked event count per `request-id` and is used for clog calculations. The `subscriptions` `map` contains gall subscriptions by `request-id`. The `heartbeat` is the SSE heartbeat [$timer](#timer).
118117
119−## `$binding`
118+### `$binding`
120119
121120```hoon
122121+$ binding
@@ -127,7 +126,7 @@ This is the state of a particular channel in the channel system. The `state` is
127126
128127A `binding` is a rule to match a URL `path` and optional `site` domain which can then be tied to an [$action](#action). A `path` of `/foo` will also match `/foo/bar`, `/foo/bar/baz`, etc. If the `site` is `~` it will be determined implicitly. A binding must be unique.
129128
130−## `$action`
129+### `$action`
131130
132131```hoon
133132+$ action
@@ -143,7 +142,7 @@ A `binding` is a rule to match a URL `path` and optional `site` domain which can
143142
144143The action to take when a [$binding](#binding) matches an incoming HTTP request.
145144
146−## `$generator`
145+### `$generator`
147146
148147```hoon
149148+$ generator
@@ -155,7 +154,7 @@ The action to take when a [$binding](#binding) matches an incoming HTTP request.
155154
156155This refers to a generator on a local ship that can handle requests. Note that serving generators via Eyre is not fully implmented and should not be used.
157156
158−## `$http-config`
157+### `$http-config`
159158
160159```hoon
161160+$ http-config
@@ -168,7 +167,7 @@ This refers to a generator on a local ship that can handle requests. Note that s
168167
169168The configuration of the runtime HTTP server itself. The `secure` field contains the PEM-encoded RSA private key and certificate or certificate chain when using HTTPS, and otherwise is `~` when using plain HTTP. The `proxy` field is not currently used. The `log` field turns on HTTP(S) access logs but is not currently implemented. The `redirect` field turns on 301 redirects to upgrade HTTP to HTTPS if the `key` and `cert` are set in `secure`.
170169
171−## `$http-rule`
170+### `$http-rule`
172171
173172```hoon
174173+$ http-rule
@@ -179,7 +178,7 @@ The configuration of the runtime HTTP server itself. The `secure` field contains
179178
180179This is for updating the server configuration. In the case of `%cert`, a `cert` of `~` clears the HTTPS cert & key, otherwise `cert` contains the PEM-encoded RSA private key and certificate or certificate chain. In the case of `%turf`, a `%put` `action` sets a domain name and a `%del` `action` removes it. The [$turf](#turf) contains the domain name.
181180
182−## `$address`
181+### `$address`
183182
184183```hoon
185184+$ address
@@ -190,7 +189,7 @@ This is for updating the server configuration. In the case of `%cert`, a `cert`
190189
191190A client IP address.
192191
193−## `$inbound-request`
192+### `$inbound-request`
194193
195194```hoon
196195+$ inbound-request
@@ -201,11 +200,11 @@ A client IP address.
201200 ==
202201```
203202
204−An inbound HTTP request and metadata. The `authenticated` field says whether the request was made with a valid session cookie. The `secure` field says whether it was made with HTTPS. The [$address](#address) is the IP address from which the request originated, except if it came from localhost and included a `Forwarded` header, in which case it's the address specified in that header. The [$request:http](#request-http) contains the HTTP request itself.
203+An inbound HTTP request and metadata. The `authenticated` field says whether the request was made with a valid session cookie. The `secure` field says whether it was made with HTTPS. The [$address](#address) is the IP address from which the request originated, except if it came from localhost and included a `Forwarded` header, in which case it's the address specified in that header. The [$request:http](#requesthttp) contains the HTTP request itself.
205204
206−# HTTP
205+## HTTP
207206
208−## `$header-list:http`
207+### `$header-list:http`
209208
210209```hoon
211210+$ header-list (list [key=@t value=@t])
@@ -213,7 +212,7 @@ An inbound HTTP request and metadata. The `authenticated` field says whether the
213212
214213An ordered list of HTTP headers. The `key` is the header name e.g `'Content-Type'` and the `value` is the value e.g. `text/html`.
215214
216−## `$method:http`
215+### `$method:http`
217216
218217```hoon
219218+$ method
@@ -230,7 +229,7 @@ An ordered list of HTTP headers. The `key` is the header name e.g `'Content-Type
230229
231230An HTTP method.
232231
233−## `$request:http`
232+### `$request:http`
234233
235234```hoon
236235+$ request
@@ -241,9 +240,9 @@ An HTTP method.
241240 ==
242241```
243242
244−A single HTTP request. The [$method:http](#method-http) is the HTTP method, the `url` is the unescaped URL, the [$header-list:http](#header-list-http) contains the HTTP headers of the request and the `body` is the actual data. An `octs` is just `[p=@ud q=@]` where `p` is the byte-length of `q`, the data.
243+A single HTTP request. The [$method:http](#methodhttp) is the HTTP method, the `url` is the unescaped URL, the [$header-list:http](#header-listhttp) contains the HTTP headers of the request and the `body` is the actual data. An `octs` is just `[p=@ud q=@]` where `p` is the byte-length of `q`, the data.
245244
246−## `$response-header:http`
245+### `$response-header:http`
247246
248247```hoon
249248+$ response-header
@@ -252,9 +251,9 @@ A single HTTP request. The [$method:http](#method-http) is the HTTP method, the
252251 ==
253252```
254253
255−The status code and [$header-list:http](#header-list-http) of an HTTP response.
254+The status code and [$header-list:http](#header-listhttp) of an HTTP response.
256255
257−## `$http-event:http`
256+### `$http-event:http`
258257
259258```hoon
260259+$ http-event
@@ -277,7 +276,7 @@ Urbit treats Earth's HTTP servers as pipes, where Urbit sends or receives one or
277276
278277Calculation of control headers such as `'Content-Length'` or `'Transfer-Encoding'` should be performed at a higher level; this structure is merely for what gets sent to or received from Earth.
279278
280−## `$simple-payload:http`
279+### `$simple-payload:http`
281280
282281```hoon
283282+$ simple-payload
@@ -287,4 +286,4 @@ Calculation of control headers such as `'Content-Length'` or `'Transfer-Encoding
287286--
288287```
289288
290−A simple, one-event response used for generators. The [$reponse-header:http](#response-header-http) contains the status code and HTTP headers. The `octs` in the `data` contains the body of the response and is a `[p=@ud q=@]` where `p` is the byte-length of `q`, the data.
289+A simple, one-event response used for generators. The [$reponse-header:http](#response-headerhttp) contains the status code and HTTP headers. The `octs` in the `data` contains the body of the response and is a `[p=@ud q=@]` where `p` is the byte-length of `q`, the data.
content/docs/arvo/eyre/examples.md+29−41
@@ -4,29 +4,17 @@ weight = 6
44template = "doc.html"
55+++
66
7−# Contents
8−
9−- [Introduction](#introduction)
10−- [Authenticating](#authenticating)
11−- [Using the Channel System](#using-the-channel-system)
12−- [Scrying](#scrying)
13−- [Direct HTTP Handling With Gall Agents](#direct-http-handling-with-gall-agents)
14−- [Generators](#generators)
15−- [Managing CORS Origins](#managing-cors-origins)
16−
17−# Introduction
18−
197This documents contains practical examples of the various ways of interacting with Eyre.
208
21−General documentation of the `task`s and methods described here are available in the [External API Reference](@/docs/arvo/eyre/external-api-ref.md) document and the [Internal API Reference](@/docs/arvo/eyre/tasks.md) document.
9+General documentation of the `task`s and methods described here are available in the [External API Reference](/docs/arvo/eyre/external-api-ref) document and the [Internal API Reference](/docs/arvo/eyre/tasks) document.
2210
23−# Authenticating
11+## Authenticating
2412
25−In most cases we must obtain a valid session cookie by [authenticating](@/docs/arvo/eyre/external-api-ref.md#authentication) with our web login code (which can be obtained by running `+code` in the dojo) before we can use Eyre's interfaces (such as the channel system or scry interface).
13+In most cases we must obtain a valid session cookie by [authenticating](/docs/arvo/eyre/external-api-ref#authentication) with our web login code (which can be obtained by running `+code` in the dojo) before we can use Eyre's interfaces (such as the channel system or scry interface).
2614
2715Here we'll try authenticating with the default fakezod code.
2816
29−Using `curl` in the unix terminal, we'll make an HTTP POST request with `"password=<code>"` in the body:
17+Using `curl` in the unix terminal, we'll make an HTTP POST request with `"password=CODE"` in the body:
3018
3119```
3220curl -i localhost:8080/~/login -X POST -d "password=lidlut-tabwed-pillex-ridrup"
@@ -44,9 +32,9 @@ set-cookie: urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm; Path=/; Max-Age=6048
4432
4533The `urbauth-....` cookie can be now be included in subsequent requests (e.g. to the channel system) by providing it in a Cookie HTTP header.
4634
47−# Using The Channel System
35+## Using The Channel System
4836
49−Here we'll look at a practical example of Eyre's channel system. You can refer to the [Channels](@/docs/arvo/eyre/external-api-ref.md#channels) section of the [External API Reference](@/docs/arvo/eyre/external-api-ref.md) document for relevant details.
37+Here we'll look at a practical example of Eyre's channel system. You can refer to the [Channels](/docs/arvo/eyre/external-api-ref#channels) section of the [External API Reference](/docs/arvo/eyre/external-api-ref) document for relevant details.
5038
5139First, we must obtain a session cookie by [authenticating](#authenticating). You will be copying the entry of the `set-cookie` field into the `--cookie` field in subsequent commands.
5240
@@ -54,7 +42,7 @@ Now that we have our cookie, we can try poking an app & simultaneously opening a
5442
5543We'll do this with an HTTP PUT request, and we'll include the cookie we obtained when we authenticated in the `Cookie` header. The URL path we'll make the request to will be `http://localhost:8080/~/channel/mychannel`. The last part of the path is the channel `UID` - the name for our new channel. Normally you'd use the current unix time plus a hash to ensure uniqueness, but in this case we'll just use `mychannel` for simplicity.
5644
57−The data will be a JSON array containing a [poke](@/docs/arvo/eyre/external-api-ref.md#poke) `action`:
45+The data will be a JSON array containing a [poke](/docs/arvo/eyre/external-api-ref#poke) `action`:
5846
5947```
6048curl --header "Content-Type: application/json" \
@@ -76,7 +64,7 @@ Now we can connect to the `mychannel` channel we opened. We do this with an HTTP
7664curl -i --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" http://localhost:8080/~/channel/my-channel
7765```
7866
79−Eyre will respond with an HTTP status code of 200 and a `content-type` of `text/event-stream`, indicating an SSE (Server Sent Event) stream. It will also send us any pending events on the channel - in this case the poke ack as a [poke](@/docs/arvo/eyre/external-api-ref.md#poke-ack) `response` for our original poke:
67+Eyre will respond with an HTTP status code of 200 and a `content-type` of `text/event-stream`, indicating an SSE (Server Sent Event) stream. It will also send us any pending events on the channel - in this case the poke ack as a [poke](/docs/arvo/eyre/external-api-ref#poke-ack) `response` for our original poke:
8068
8169```
8270HTTP/1.1 200 ok
@@ -97,7 +85,7 @@ Normally this event stream would be handled by an EventSource object or similar
9785
9886Leaving the event stream connection open, in another shell session on unix we'll try subscribing to the watch path of a Gall agent - the `/updates` watch path of `graph-store` in this case.
9987
100−We'll do this in the same way as the initial poke, except this time it will be a [subscribe](@/docs/arvo/eyre/external-api-ref.md#subscribe) `action`:
88+We'll do this in the same way as the initial poke, except this time it will be a [subscribe](/docs/arvo/eyre/external-api-ref#subscribe) `action`:
10189
10290```
10391curl --header "Content-Type: application/json" \
@@ -109,21 +97,21 @@ curl --header "Content-Type: application/json" \
10997
11098Notice we've incremented the `id` to `2`. Eyre doesn't require IDs to be sequential, merely numerical and unique, but sequential IDs are typically the most practical.
11199
112−Back in the event stream, we'll see a positive watch ack as a [subscribe](@/docs/arvo/eyre/external-api-ref.md#watch-ack) `response`, meaning the subscription has been successful:
100+Back in the event stream, we'll see a positive watch ack as a [subscribe](/docs/arvo/eyre/external-api-ref#watch-ack) `response`, meaning the subscription has been successful:
113101
114102```
115103id: 1
116104data: {"ok":"ok","id":2,"response":"subscribe"}
117105```
118106
119−Now we'll try trigger an event on our event stream. In fakezod's Landscape, create a new chat channel named "test". You should see the `add-graph` `graph-update` come through on our channel in a [diff](@/docs/arvo/eyre/external-api-ref.md#diff) `response`:
107+Now we'll try trigger an event on our event stream. In fakezod's Landscape, create a new chat channel named "test". You should see the `add-graph` `graph-update` come through on our channel in a [diff](/docs/arvo/eyre/external-api-ref#diff) `response`:
120108
121109```
122110id: 2
123111data: {"json":{"graph-update":{"add-graph":{"graph":{},"resource":{"name":"test-1183","ship":"zod"},"mark":"graph-validator-chat","overwrite":false}}},"id":2,"response":"diff"}
124112```
125113
126−All events we receive must be `ack`ed so Eyre knows we've successfully received them. To do this we'll send an [ack](@/docs/arvo/eyre/external-api-ref.md#ack) `action` which specifies the `event-id` of the event in question - `2` in this case:
114+All events we receive must be `ack`ed so Eyre knows we've successfully received them. To do this we'll send an [ack](/docs/arvo/eyre/external-api-ref#ack) `action` which specifies the `event-id` of the event in question - `2` in this case:
127115
128116```
129117curl --header "Content-Type: application/json" \
@@ -135,7 +123,7 @@ curl --header "Content-Type: application/json" \
135123
136124This same pattern would be repeated for all subsequent events. Note that when you `ack` one event, you also implicitly `ack` all previous events, so in this case event `1` will also be `ack`ed.
137125
138−When we're finished, we can unsubscribe from `graph-store` `/update`. We do this by sending Eyre a [unsubscribe](@/docs/arvo/eyre/external-api-ref.md#unsubscribe) `action`, and specify the request ID of the original `subscribe` `action` in the `subscription` field - `2` in our case:
126+When we're finished, we can unsubscribe from `graph-store` `/update`. We do this by sending Eyre a [unsubscribe](/docs/arvo/eyre/external-api-ref#unsubscribe) `action`, and specify the request ID of the original `subscribe` `action` in the `subscription` field - `2` in our case:
139127
140128```
141129curl --header "Content-Type: application/json" \
@@ -147,7 +135,7 @@ curl --header "Content-Type: application/json" \
147135
148136Unlike `poke` and `subscribe` actions, Eyre doesn't acknowledge `unsubscribe`s, but we'll now have stopped receiving updates from `graph-store`.
149137
150−Finally, let's close the channel itself. We can do this simply by sending Eyre a [delete](@/docs/arvo/eyre/external-api-ref.md#delete-channel) `action`:
138+Finally, let's close the channel itself. We can do this simply by sending Eyre a [delete](/docs/arvo/eyre/external-api-ref#delete-channel) `action`:
151139
152140```
153141curl --header "Content-Type: application/json" \
@@ -159,9 +147,9 @@ curl --header "Content-Type: application/json" \
159147
160148With our channel deleted, we can now close the connection on the client side.
161149
162−# Scrying
150+## Scrying
163151
164−Here we'll look at performing scries through Eyre. You can refer to the [Scry](@/docs/arvo/eyre/external-api-ref.md#scry) section of the [External API Reference](@/docs/arvo/eyre/external-api-ref.md) document for relevant details.
152+Here we'll look at performing scries through Eyre. You can refer to the [Scry](/docs/arvo/eyre/external-api-ref#scry) section of the [External API Reference](/docs/arvo/eyre/external-api-ref) document for relevant details.
165153
166154First we must obtain a session cookie by [authenticating](#authenticating).
167155
@@ -213,13 +201,13 @@ content-type: text/html
213201<html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>There was an error while handling the request for /foo/bar/baz.json.</p><code>no scry result</code></body></html>
214202```
215203
216−# Direct HTTP Handling With Gall Agents
204+## Direct HTTP Handling With Gall Agents
217205
218206In many cases you'll just want to interact with Gall agents through the JSON API of the channel system, but it's also possible to bypass all that and just deal with HTTP requests directly. Here we'll take a look at how that practically works.
219207
220−You can refer to the [%connect](@/docs/arvo/eyre/tasks.md#connect) section of the [Internal API Reference](@/docs/arvo/eyre/tasks.md) document for relevant details.
208+You can refer to the [%connect](/docs/arvo/eyre/tasks#connect) section of the [Internal API Reference](/docs/arvo/eyre/tasks) document for relevant details.
221209
222−Here's a Gall agent that demonstrates this method. It binds the URL path `/foo`, serves `<h1>Hello, World!</h1>` for GET requests and a `405` error for all others. It also prints debug information to the terminal as various things happen.
210+Here's a Gall agent that demonstrates this method. It binds the URL path `/foo`, serves `Hello, World!` for GET requests and a `405` error for all others. It also prints debug information to the terminal as various things happen.
223211
224212Note that this example does a lot of things manually for demonstrative purposes. In practice you'd likely want to use a library like `/lib/server.hoon` to cut down on boilerplate code.
225213
@@ -336,7 +324,7 @@ activated app home/eyre-agent
336324[unlinked from [p=~zod q=%eyre-agent]]
337325```
338326
339−Now, first we need to bind a URL to our app. In the `++ on-poke` arm, our agent will send a [%connect](@/docs/arvo/eyre/tasks.md#connect) `task` to Eyre when poked with `%bind`:
327+Now, first we need to bind a URL to our app. In the `++ on-poke` arm, our agent will send a [%connect](/docs/arvo/eyre/tasks#connect) `task` to Eyre when poked with `%bind`:
340328
341329```hoon
342330 %noun
@@ -436,11 +424,11 @@ Eyre subscribed to /http-response/~.eyre_0v3.1knjk.l544e.5uds6.fn9l2.f8929.
436424
437425This is a very rudimentary app but it demonstrates the basic mechanics of dealing with HTTP requests and serving responses.
438426
439−# Generators
427+## Generators
440428
441429Here we'll look at running a generator via Eyre. Eyre doesn't have a mediated JSON API for generators, instead it just passes through the HTTP request and returns the HTTP response composed by the generator.
442430
443−You can refer to the [%serve](@/docs/arvo/eyre/tasks.md#serve) section of the [Internal API Reference](@/docs/arvo/eyre/tasks.md) document for relevant details.
431+You can refer to the [%serve](/docs/arvo/eyre/tasks#serve) section of the [Internal API Reference](/docs/arvo/eyre/tasks) document for relevant details.
444432
445433Here's a very simple generator that will just echo back the body of the request (if available) along with the current datetime. You can save it in the `/gen` directory and `|commit %home`.
446434
@@ -475,7 +463,7 @@ The sample of the second nested gate must be:
475463[authenticated=? =request:http]
476464```
477465
478−The return type of the generator must be [simple-payload:http](@/docs/arvo/eyre/data-types.md#simple-payload-http). If you look at our example generator you'll see it meets these requirements.
466+The return type of the generator must be [$simple-payload:http](/docs/arvo/eyre/data-types#simple-payloadhttp). If you look at our example generator you'll see it meets these requirements.
479467
480468Because generators return the entire HTTP message as a single `simple-payload`, Eyre can calculate the `content-length` itself and automatically add the header.
481469
@@ -485,7 +473,7 @@ In order to make our generator available, we must bind it to a URL path. To do t
485473[%serve =binding =generator]
486474```
487475
488−The [binding](@/docs/arvo/eyre/data-types.md#binding) specifies the site and URL path, and the [generator](@/docs/arvo/eyre/data-types.md#generator) specifies the `desk`, the `path` to the generator, and arguments. Note that the passing of arguments to the generator by Eyre is not currently implemented, so you can just leave that as `~` since it won't do anything.
476+The [$binding](/docs/arvo/eyre/data-types#binding) specifies the site and URL path, and the [$generator](/docs/arvo/eyre/data-types#generator) specifies the `desk`, the `path` to the generator, and arguments. Note that the passing of arguments to the generator by Eyre is not currently implemented, so you can just leave that as `~` since it won't do anything.
489477
490478Let's bind our generator to the `/mygen` URL path with the `|pass` command in the dojo:
491479
@@ -516,9 +504,9 @@ Content-Length: 41
516504blah blah blah
517505```
518506
519−# Managing CORS Origins
507+## Managing CORS Origins
520508
521−Here we'll look at approving and rejecting a CORS origin by passing Clay a [%approve-origin](@/docs/arvo/eyre/tasks.md#approve-origin) `task` and [%reject-origin](@/docs/arvo/eyre/tasks.md#reject-origin) `task` respectively.
509+Here we'll look at approving and rejecting a CORS origin by passing Clay a [%approve-origin](/docs/arvo/eyre/tasks#approve-origin) `task` and [%reject-origin](/docs/arvo/eyre/tasks#reject-origin) `task` respectively.
522510
523511In this example we'll use more manual methods for demonstrative purposes but note there are also the `|cors-approve` and `|cors-reject` generators to approve/reject origins from the dojo, and the `+cors-registry` generator for viewing the CORS configuration.
524512
@@ -528,7 +516,7 @@ First, using `|pass` in the dojo, let's approve the origin `http://foo.example`
528516|pass [%e [%approve-origin 'http://foo.example']]
529517```
530518
531−Now if we scry for the [approved](@/docs/arvo/eyre/scry.md#cors-approved) CORS `set`:
519+Now if we scry for the [approved](/docs/arvo/eyre/scry#cors-approved) CORS `set`:
532520
533521```
534522> .^(approved=(set @t) %ex /=//=/cors/approved)
@@ -566,7 +554,7 @@ Now we'll try rejecting an `origin`. Back in the dojo, let's `|pass` Eyre a `%re
566554|pass [%e [%reject-origin 'http://bar.example']]
567555```
568556
569−If we scry for the [rejected](@/docs/arvo/eyre/scry.md#cors-rejected) CORS `set`:
557+If we scry for the [rejected](/docs/arvo/eyre/scry#cors-rejected) CORS `set`:
570558
571559```
572560> .^(rejected=(set @t) %ex /=//=/cors/rejected)
@@ -615,7 +603,7 @@ Connection: close
615603Server: urbit/vere-1.5
616604```
617605
618−Now if we scry for the [requests](@/docs/arvo/eyre/scry.md#cors-requests) CORS `set`:
606+Now if we scry for the [requests](/docs/arvo/eyre/scry#cors-requests) CORS `set`:
619607
620608```
621609> .^(requests=(set @t) %ex /=//=/cors/requests)
content/docs/arvo/eyre/external-api-ref.md+35−57
@@ -4,31 +4,9 @@ weight = 2
44template = "doc.html"
55+++
66
7−# Contents
8−
9−- [Introduction](#introduction)
10−- [Authentication](#authentication)
11−- [Channels](#channels)
12− - [HTTP Requests](#http-requests)
13− - [Actions](#actions)
14− - [Poke](#poke)
15− - [Subscribe](#subscribe)
16− - [Ack](#ack)
17− - [Unsubscribe](#unsubscribe)
18− - [Delete Channel](#delete-channel)
19− - [Responses](#responses)
20− - [Poke Ack](#poke-ack)
21− - [Watch Ack](#watch-ack)
22− - [Diff](#diff)
23− - [Quit](#quit)
24−- [Scry](#scry)
25−- [Spider](#spider)
26−
27−# Introduction
28−
29−This document contains reference information about Eyre's external APIs including [the channel system](#channels) and [scries](#scry). Each section will also have practical examples in the [Examples](@/docs/arvo/eyre/examples.md) document.
30−
31−# Authentication
7+This document contains reference information about Eyre's external APIs including [the channel system](#channels) and [scries](#scry). Each section will also have practical examples in the [Examples](/docs/arvo/eyre/examples) document.
8+
9+## Authentication
3210
3311To use Eyre's channel system, run threads or perform scries you must first obtain a session cookie by authenticating with the following HTTP request:
3412
@@ -36,7 +14,7 @@ To use Eyre's channel system, run threads or perform scries you must first obtai
3614| ----------- | -------------------------------------- | ---------- | ----------------------------------------------------------------------------------- |
3715| `POST` | `password=lidlut-tabwed-pillex-ridrup` | `/~/login` | The password is your web login code which can be obtained with `+code` in the dojo. |
3816
39−See the [examples](@/docs/arvo/eyre/examples.md#authenticating) for an example of how to do this using the curl.
17+See the [examples](/docs/arvo/eyre/examples#authenticating) for an example of how to do this using the curl.
4018
4119Eyre's response will include a `set-cookie` header like:
4220
@@ -50,7 +28,7 @@ The `urbauth-{...}` cookie provided must be included in a `cookie` header with a
5028cookie: urbauth-~zod=0v4.ilskp.psv00.t09r0.l8rps.3n97v
5129```
5230
53−# Channels
31+## Channels
5432
5533Eyre's channel system is the primary way of interacting with Gall agents from outside of Urbit.
5634
@@ -73,9 +51,9 @@ All the events that Eyre sends you on a channel must be [ack](#ack)ed so that Ey
7351
7452When you're finished with a channel, you can send Eyre a [delete action](#delete-channel) to close it.
7553
76−See the [Using the Channel System](@/docs/arvo/eyre/examples.md#using-the-channel-system) section of the [Examples](@/docs/arvo/eyre/examples.md) document for a practical example.
54+See the [Using the Channel System](/docs/arvo/eyre/examples#using-the-channel-system) section of the [Examples](/docs/arvo/eyre/examples) document for a practical example.
7755
78−## HTTP Requests
56+### HTTP Requests
7957
8058[Actions](#actions) are sent to Eyre in HTTP PUT requests:
8159
@@ -102,7 +80,7 @@ This is for poking a Gall agent.
10280| `mark` | String | `'helm-hi'` | Type of data. Must correspond to a mark definition in `/mar`. |
10381| `json` | Any | `'hello'` | Actual payload. Any JSON type, determined by app. |
10482
105−**Example**
83+#### Example
10684
10785```json
10886{
@@ -115,7 +93,7 @@ This is for poking a Gall agent.
11593}
11694```
11795
118−**Response**
96+#### Response
11997
12098Eyre will send a [poke ack](#poke-ack) as an SSE event on the channel event stream.
12199
@@ -131,7 +109,7 @@ This is for subscribing to a watch `path` of a Gall agent.
131109| `app` | String | `'graph-store'` | Name of the gall agent to which you're subscribing. |
132110| `path` | String | `'/updates'` | The path to watch. Depends on the app. |
133111
134−**Example**
112+#### Example
135113
136114```json
137115{
@@ -143,7 +121,7 @@ This is for subscribing to a watch `path` of a Gall agent.
143121}
144122```
145123
146−**Response**
124+#### Response
147125
148126Eyre will send back a [watch ack](#watch-ack). If subscribing was successful, you will also begin receiving any [diff](#diff)s sent by the Gall agent on the specified `path`.
149127
@@ -157,7 +135,7 @@ This is for acknowledging an SSE event. If you `ack` one event, you also implici
157135| `action` | String | `'ack'` | The kind of action. |
158136| `event-id` | Number | `7` | ID of SSE event up to which you're acknowledging receipt |
159137
160−**Example**
138+#### Example
161139
162140```json
163141{
@@ -167,7 +145,7 @@ This is for acknowledging an SSE event. If you `ack` one event, you also implici
167145}
168146```
169147
170−**Response**
148+#### Response
171149
172150Eyre will not respond to an `ack` action.
173151
@@ -181,7 +159,7 @@ This is for unsubscribing from a Gall agent watch `path` to which you've previou
181159| `action` | String | `unsubscribe` | The kind of action. |
182160| `subscription` | Number | `2` | Request ID of the initial `subscribe` action from earlier. |
183161
184−**Example**
162+#### Example
185163
186164```json
187165{
@@ -191,7 +169,7 @@ This is for unsubscribing from a Gall agent watch `path` to which you've previou
191169}
192170```
193171
194−**Response**
172+#### Response
195173
196174Eyre will not respond to an `unsubscribe` action.
197175
@@ -204,7 +182,7 @@ This is for deleting the channel itself.
204182| `id` | Number | `5` | ID for keeping track of sent messages. |
205183| `action` | String | `'delete'` | The kind of action. |
206184
207−**Example**
185+#### Example
208186
209187```json
210188{
@@ -213,7 +191,7 @@ This is for deleting the channel itself.
213191}
214192```
215193
216−**Response**
194+#### Response
217195
218196Eyre will not respond to a `delete` action.
219197
@@ -223,7 +201,7 @@ Eyre will not respond to a `delete` action.
223201
224202This acknowledgement comes in response to a [poke](#poke) action. A poke ack with an `ok` key means the poke succeeded. A poke ack with an `err` key means the poke failed.
225203
226−**Positive Poke Ack**
204+#### Positive Poke Ack
227205
228206| Key | JSON Type | Example Value | Description |
229207| ---------- | --------- | ------------- | -------------------------------------------- |
@@ -231,7 +209,7 @@ This acknowledgement comes in response to a [poke](#poke) action. A poke ack wit
231209| `id` | Number | `1` | Request ID of the `poke` being acknowledged. |
232210| `response` | String | `'poke'` | The kind of action being acknowledged. |
233211
234−**Example**
212+#### Example
235213
236214```json
237215{
@@ -241,7 +219,7 @@ This acknowledgement comes in response to a [poke](#poke) action. A poke ack wit
241219}
242220```
243221
244−**Negative Poke Ack**
222+#### Negative Poke Ack
245223
246224| Key | JSON Type | Example Value | Description |
247225| ---------- | --------- | ---------------- | --------------------------------------------------------------------- |
@@ -249,7 +227,7 @@ This acknowledgement comes in response to a [poke](#poke) action. A poke ack wit
249227| `id` | Number | `1` | Request ID of the `poke` being acknowledged. |
250228| `response` | String | `'poke'` | The kind of action being acknowledged. |
251229
252−**Example**
230+#### Example
253231
254232```json
255233{
@@ -259,7 +237,7 @@ This acknowledgement comes in response to a [poke](#poke) action. A poke ack wit
259237}
260238```
261239
262−**Action Required**
240+#### Action Required
263241
264242You must ack the event.
265243
@@ -267,7 +245,7 @@ You must ack the event.
267245
268246This acknowledgement comes in response to a [subscribe](#subscribe) action. A watch ack with an `ok` key means the subscription was successful. A watch ack with an `err` key means the subscription failed.
269247
270−**Positive Watch Ack**
248+#### Positive Watch Ack
271249
272250| Key | JSON Type | Example Value | Description |
273251| ---------- | --------- | ------------- | --------------------------------------------- |
@@ -275,7 +253,7 @@ This acknowledgement comes in response to a [subscribe](#subscribe) action. A wa
275253| `id` | Number | `2` | Request ID of the initial `subscribe` action. |
276254| `response` | String | `'subscribe'` | The kind of action being acknowledged. |
277255
278−**Example**
256+#### Example
279257
280258```json
281259{
@@ -285,7 +263,7 @@ This acknowledgement comes in response to a [subscribe](#subscribe) action. A wa
285263}
286264```
287265
288−**Negative Watch Ack**
266+#### Negative Watch Ack
289267
290268| Key | JSON Type | Example Value | Description |
291269| ---------- | --------- | ---------------- | --------------------------------------------------------------------- |
@@ -293,7 +271,7 @@ This acknowledgement comes in response to a [subscribe](#subscribe) action. A wa
293271| `id` | Number | `2` | Request ID of the initial `subscribe` action. |
294272| `response` | String | `'subscribe'` | The kind of action being acknowledged. |
295273
296−**Example**
274+#### Example
297275
298276```json
299277{
@@ -303,7 +281,7 @@ This acknowledgement comes in response to a [subscribe](#subscribe) action. A wa
303281}
304282```
305283
306−**Action Required**
284+#### Action Required
307285
308286You must ack the event.
309287
@@ -317,7 +295,7 @@ All `fact`s sent by a Gall agent on the `path` to which you've subscribed are de
317295| `id` | Number | `3` | Request ID of the initial `subscribe` action from earlier. |
318296| `response` | String | `'diff'` | The kind of response. All `fact`s are marked `'diff'`. |
319297
320−**Example**
298+#### Example
321299
322300```json
323301{
@@ -327,7 +305,7 @@ All `fact`s sent by a Gall agent on the `path` to which you've subscribed are de
327305}
328306```
329307
330−**Action Required**
308+#### Action Required
331309
332310You must [ack](#ack) each `diff` that comes in the event stream.
333311
@@ -340,7 +318,7 @@ A `quit` comes in when a subscription has been ended. You may be intentionally k
340318| `id` | Number | `4` | Request ID of the initial `subscribe` action. |
341319| `response` | String | `'quit'` | The kind of response. |
342320
343−**Example**
321+#### Example
344322
345323```json
346324{
@@ -349,11 +327,11 @@ A `quit` comes in when a subscription has been ended. You may be intentionally k
349327}
350328```
351329
352−**Action Required**
330+#### Action Required
353331
354332You must ack the event and you may wish to try and re[subscribe](#subscribe).
355333
356−# Scry
334+## Scry
357335
358336A scry is a read-only request for some data.
359337
@@ -374,8 +352,8 @@ The `{mark}` is the type you want returned. It needn't just be `json` as with th
374352
375353If your session cookie is invalid or missing, Eyre will respond with a 403 Forbidden status. If the scry endpoint cannot be found, Eyre will respond with a 404 Missing status. If the `mark` conversions can't be done, Eyre will respond with a 500 Internal Server Error status. Otherwise, Eyre will respond with a 200 OK status with the requested data in the body of the HTTP response.
376354
377−See the [Scrying](@/docs/arvo/eyre/examples.md#scrying) section of the [Examples](@/docs/arvo/eyre/examples.md) document for a practical example.
355+See the [Scrying](/docs/arvo/eyre/examples#scrying) section of the [Examples](/docs/arvo/eyre/examples) document for a practical example.
378356
379−# Spider
357+## Spider
380358
381−See the [HTTP API](@/docs/userspace/threads/http-api.md) section of the [Threads](@/docs/userspace/threads/overview.md) documentation.
359+See the [HTTP API](/docs/userspace/threads/http-api) section of the [Threads](/docs/userspace/threads/overview) documentation.
content/docs/arvo/eyre/eyre.md+20−20
@@ -8,54 +8,54 @@ Eyre is the webserver vane.
88
99HTTP messages come in from outside and Eyre produces HTTP messages in response. In general, apps do not call Eyre; rather, Eyre calls apps. Eyre has a number of ways to handle such HTTP requests which we'll briefly describe.
1010
11−# Authentication
11+## Authentication
1212
13−Most types of requests require the client provide a valid session cookie which is obtained by authenticating with your ship's web login code. Authentication is documented in the [Authentication](@/docs/arvo/eyre/external-api-ref.md#authentication) section of the [External API Reference](@/docs/arvo/eyre/external-api-ref.md) documentation.
13+Most types of requests require the client provide a valid session cookie which is obtained by authenticating with your ship's web login code. Authentication is documented in the [Authentication](/docs/arvo/eyre/external-api-ref#authentication) section of the [External API Reference](/docs/arvo/eyre/external-api-ref) documentation.
1414
15−# The Channel System
15+## The Channel System
1616
1717Eyre's channel system is the primary way of interacting with Gall agents from outside of Urbit. It provides a simple JSON API that allows you to send data to apps and subscribe for updates from apps. Updates come back on a SSE ([Server Sent Event](https://html.spec.whatwg.org/#server-sent-events)) stream which you can easily handle with an EventSource object in Javascript or the equivalent in whichever language you prefer.
1818
1919The channel system is designed to be extremely simple with just a handful of `action` and `response` JSON objects to deal. Essentially it's a thin layer on top of the underlying Gall agent interface. You can poke agents, subscribe for updates, etc, just like you would from within Urbit.
2020
21−Detailed documentation of the channel system's JSON API is provided in the [External API Reference](@/docs/arvo/eyre/external-api-ref.md) document with corresponding examples in the [Examples](@/docs/arvo/eyre/examples.md#using-the-channel-system) document.
21+Detailed documentation of the channel system's JSON API is provided in the [External API Reference](/docs/arvo/eyre/external-api-ref) document with corresponding examples in the [Examples](/docs/arvo/eyre/examples#using-the-channel-system) document.
2222
23−# Scrying
23+## Scrying
2424
2525Along with the channel system, Eyre also provides a way to make read-only requests for data which are called scries. Eyre's scry interface is separate to the channel system but may be useful in conjunction with it.
2626
27−Details of Eyre's scry API are in the [Scry](@/docs/arvo/eyre/external-api-ref.md#scry) section of the [External API Reference](@/docs/arvo/eyre/external-api-ref.md) document.
27+Details of Eyre's scry API are in the [Scry](/docs/arvo/eyre/external-api-ref#scry) section of the [External API Reference](/docs/arvo/eyre/external-api-ref) document.
2828
29−# Spider Threads
29+## Spider Threads
3030
31−Spider (the Gall agent that manages threads) has an Eyre binding that allows you to run threads through Eyre. Spider's [HTTP API](@/docs/userspace/threads/http-api.md) is not part of Eyre proper, so is documented separately in the [Threads](@/docs/userspace/threads/overview.md) documentation.
31+Spider (the Gall agent that manages threads) has an Eyre binding that allows you to run threads through Eyre. Spider's [HTTP API](/docs/userspace/threads/http-api) is not part of Eyre proper, so is documented separately in the [Threads](/docs/userspace/threads/overview) documentation.
3232
33−# Generators
33+## Generators
3434
3535Generators, which are like Hoon scripts, can also be used through Eyre. Rather than having a predefined JSON API, they instead handle HTTP requests and return HTTP responses directly, and are therefore a more complex case that you're less likely to use.
3636
37−Their usage is explained in the [%serve](@/docs/arvo/eyre/tasks.md#serve) section of the [Internal API Reference](@/docs/arvo/eyre/tasks.md) documentation and a practical example is provided in the [Generators](@/docs/arvo/eyre/examples.md#generators) section of the [Examples](@/docs/arvo/eyre/examples.md) document.
37+Their usage is explained in the [%serve](/docs/arvo/eyre/tasks#serve) section of the [Internal API Reference](/docs/arvo/eyre/tasks) documentation and a practical example is provided in the [Generators](/docs/arvo/eyre/examples#generators) section of the [Examples](/docs/arvo/eyre/examples) document.
3838
39−# Direct HTTP Handling With Gall Agents
39+## Direct HTTP Handling With Gall Agents
4040
4141As well as the [Channel System](#the-channel-system) and [Scries](#scrying), it's also possible for Gall agents to deal directly with HTTP requests. This method is much more complicated than the channel system so you're unlikely to use it unless you want to build a custom HTTP-based API or something like that.
4242
43−This method is explained in the [%connect](@/docs/arvo/eyre/tasks.md#connect) section of the [Internal API Reference](@/docs/arvo/eyre/tasks.md) document and a detailed example is provided in the [Direct HTTP Handling With Gall Agents](@/docs/arvo/eyre/examples.md#direct-http-handling-with-gall-agents) section of the [Examples](@/docs/arvo/eyre/examples.md) document.
43+This method is explained in the [%connect](/docs/arvo/eyre/tasks#connect) section of the [Internal API Reference](/docs/arvo/eyre/tasks) document and a detailed example is provided in the [Direct HTTP Handling With Gall Agents](/docs/arvo/eyre/examples#direct-http-handling-with-gall-agents) section of the [Examples](/docs/arvo/eyre/examples) document.
4444
45−# Cross-Origin Resource Sharing
45+## Cross-Origin Resource Sharing
4646
4747Eyre supports both simple [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) requests and OPTIONS preflight requests. It has a CORS registry with three categories - `approved`, `rejected` and `requests`. Eyre will respond positively for origins in its `approved` list and negatively for all others. Eyre will add origins in requests that it doesn't have in either its `approved` or `rejected` lists to its `requests` list. Eyre always allows all methods and headers over CORS.
4848
49−There are three generators - `+cors-registry`, `|cors-approve`, and `|cors-reject` to view, approve, and deny origins respectively from the dojo. Eyre also has [tasks](@/docs/arvo/eyre/tasks.md) to [approve](@/docs/arvo/eyre/tasks.md#approve-origin) and [reject](@/docs/arvo/eyre/tasks.md#reject-origin) origins programmatically, and a number of [scry endpoints](@/docs/arvo/eyre/scry.md) to query them. Examples are also included in the [Managing CORS Origins](@/docs/arvo/eyre/examples.md#managing-cors-origins) section of the Examples document.
49+There are three generators - `+cors-registry`, `|cors-approve`, and `|cors-reject` to view, approve, and deny origins respectively from the dojo. Eyre also has [tasks](/docs/arvo/eyre/tasks) to [approve](/docs/arvo/eyre/tasks#approve-origin) and [reject](/docs/arvo/eyre/tasks#reject-origin) origins programmatically, and a number of [scry endpoints](/docs/arvo/eyre/scry) to query them. Examples are also included in the [Managing CORS Origins](/docs/arvo/eyre/examples#managing-cors-origins) section of the Examples document.
5050
51−# Eyre Documentation Sections
51+## Sections
5252
53−- [External API Reference](@/docs/arvo/eyre/external-api-ref.md) - Details of Eyre's external API including the channel system's JSON API.
53+[External API Reference](/docs/arvo/eyre/external-api-ref) - Details of Eyre's external API including the channel system's JSON API.
5454
55−- [Internal API Reference](@/docs/arvo/eyre/tasks.md) - The `task`s Eyre takes and the `gift`s it returns.
55+[Internal API Reference](/docs/arvo/eyre/tasks) - The `task`s Eyre takes and the `gift`s it returns.
5656
57−- [Scry Reference](@/docs/arvo/eyre/scry.md) - The scry endpoints of Eyre.
57+[Scry Reference](/docs/arvo/eyre/scry) - The scry endpoints of Eyre.
5858
59−- [Data Types](@/docs/arvo/eyre/data-types.md) - Reference documentation of the various data types used by Eyre.
59+[Data Types](/docs/arvo/eyre/data-types) - Reference documentation of the various data types used by Eyre.
6060
61−- [Examples](@/docs/arvo/eyre/examples.md) - Practical examples of the different ways of using Eyre.
61+[Examples](/docs/arvo/eyre/examples) - Practical examples of the different ways of using Eyre.
content/docs/arvo/eyre/scry.md+31−49
@@ -4,35 +4,17 @@ weight = 4
44template = "doc.html"
55+++
66
7−## Contents
8−
9−- [Introduction](#introduction)
10−- [/cors](#cors) - CORS settings.
11− - [/cors/requests](#cors-requests) - Requested origins.
12− - [/cors/approved](#cors-approved) - Approved origins.
13− - [/cors/approved/\<origin\>](#cors-approved-origin) - Check if origin approved.
14− - [/cors/rejected](#cors-rejected) - Rejected origins.
15− - [/cors/rejected/\<origin\>](#cors-rejected-origin) - Check if origin rejected.
16−- [/authenticated/cookie/\<cookie\>](#authenticated-cookie-cookie) - Check if cookie authenticated.
17−- [bindings](#bindings) - URL path bindings.
18−- [connections](#connections) - Open http connections.
19−- [authentication-state](#authentication-state) - Authentication details.
20−- [channel-state](#channel-state) - Details of each channel.
21−- [host](#host) - Host details.
22−
23−# Introduction
24−
257Here are all of Eyre's scry endpoints. There's not too many and they mostly deal with either CORS settings or aspects of the state of connections.
268
27−The first few have a `care` of `x` and are a scry like `.^(<type> %ex /=//=/<some-path>)` (note the empty `desk`). The rest have no `care` and the tag replaces the `desk` like `.^(<type> %e /=<something>=)`.
9+The first few have a `care` of `x` and are a scry like `.^({TYPE} %ex /=//=/{SOME-PATH})` (note the empty `desk`). The rest have no `care` and the tag replaces the `desk` like `.^({TYPE} %e /={SOMETHING}=)`.
2810
2911All examples are run from the dojo.
3012
31−# `/cors`
13+## `/cors`
3214
33−An `x` scry with a `path` of `/cors` will return Eyre's CORS origin registry. The type returned is a [cors-registry](@/docs/arvo/eyre/data-types.md#cors-registry) which contains the `set`s of approved, rejected and requested origins.
15+An `x` scry with a `path` of `/cors` will return Eyre's CORS origin registry. The type returned is a [cors-registry](/docs/arvo/eyre/data-types#cors-registry) which contains the `set`s of approved, rejected and requested origins.
3416
35−Example:
17+### Example
3618
3719```
3820> .^(cors-registry:eyre %ex /=//=/cors)
@@ -46,7 +28,7 @@ Example:
4628
4729An `x` scry with a `path` of `/cors/requests` will return the `set` of pending origin requests. These are origins that were in an `Origin: ...` HTTP header but weren't in the existing approved or rejected sets. The type returned is a `(set origin:eyre)`.
4830
49−Example:
31+### Example
5032
5133```
5234> .^(requests=(set origin:eyre) %ex /=//=/cors/requests)
@@ -57,20 +39,20 @@ requests={~~http~3a.~2f.~2f.baz~.example}
5739
5840An `x` scry with a `path` of `/cors/approved` will return the `set` of approved CORS origins. The type returned is a `(set origin:eyre)`.
5941
60−Example:
42+### Example
6143
6244```
6345> .^(approved=(set origin:eyre) %ex /=//=/cors/approved)
6446approved={~~http~3a.~2f.~2f.foo~.example}
6547```
6648
67−## `/cors/approved/<origin>`
49+## `/cors/approved/{ORIGIN}`
6850
69−An `x` scry whose `path` is `/cors/approved/<origin>` tests whether the given origin URL is in the `approved` set of the CORS registry. The type returned is a simple `?`.
51+An `x` scry whose `path` is `/cors/approved/{ORIGIN}` tests whether the given origin URL is in the `approved` set of the CORS registry. The type returned is a simple `?`.
7052
7153The origin URL is a `@t`, but since `@t` may not be valid in a path, it must be encoded in a `@ta` using `+scot` like `(scot %t 'foo')` rather than just `'foo'`.
7254
73−Examples:
55+### Examples
7456
7557```
7658> .^(? %ex /=//=/cors/approved/(scot %t 'http://foo.example'))
@@ -86,20 +68,20 @@ Examples:
8668
8769An `x` scry with a `path` of `/cors/rejected` will return the `set` of rejected CORS origins. The type returned is a `(set origin:eyre)`.
8870
89−Example:
71+### Example
9072
9173```
9274> .^(rejected=(set origin:eyre) %ex /=//=/cors/rejected)
9375rejected={~~http~3a.~2f.~2f.bar~.example}
9476```
9577
96−## `/cors/rejected/<origin>`
78+## `/cors/rejected/{ORIGIN}`
9779
98−An `x` scry whose `path` is `/cors/rejected/<origin>` tests whether the given origin URL is in the `rejected` set of the CORS registry. The type returned is a simple `?`.
80+An `x` scry whose `path` is `/cors/rejected/{ORIGIN}` tests whether the given origin URL is in the `rejected` set of the CORS registry. The type returned is a simple `?`.
9981
10082The origin URL must be a cord-encoded `@t` rather than just the plain `@t`, so you'll have to do something like `(scot %t 'foo')` rather than just `'foo'`.
10183
102−Examples:
84+### Examples
10385
10486```
10587> .^(? %ex /=//=/cors/rejected/(scot %t 'http://bar.example'))
@@ -111,13 +93,13 @@ Examples:
11193%.n
11294```
11395
114−# `/authenticated/cookie/<cookie>`
96+## `/authenticated/cookie`
11597
116−An `x` scry whose `path` is `/authenticated/cookies/<cookie>` tests whether the given cookie is currently valid. The type returned is a `?`.
98+An `x` scry whose `path` is `/authenticated/cookie/{COOKIE}` tests whether the given cookie is currently valid. The type returned is a `?`.
11799
118−The cookie must be the full cookie including the `urbauth-<ship>=` part. The cookie must be a cord-encoded `@t` rather than just a plain `@t`, so you'll have to do something like `(scot %t 'foo')` rather than just `'foo'`.
100+The cookie must be the full cookie including the `urbauth-{SHIP}=` part. The cookie must be a cord-encoded `@t` rather than just a plain `@t`, so you'll have to do something like `(scot %t 'foo')` rather than just `'foo'`.
119101
120−Examples:
102+### Examples
121103
122104```
123105> .^(? %ex /=//=/authenticated/cookie/(scot %t 'urbauth-~zod=0vvndn8.bfsjj.j3614.k40ha.8fomi'))
@@ -129,11 +111,11 @@ Examples:
129111%.n
130112```
131113
132−# `bindings`
114+## `%bindings`
133115
134−A scry with `bindings` in place of the `desk` in the `beak` will return Eyre's URL path bindings. The type returned is a `(list [binding:eyre duct action:eyre])` (see the [binding](@/docs/arvo/eyre/data-types.md#binding) & [action](@/docs/arvo/eyre/data-types.md#action) sections of the Data Types document for details).
116+A scry with `bindings` in place of the `desk` in the `beak` will return Eyre's URL path bindings. The type returned is a `(list [binding:eyre duct action:eyre])` (see the [$binding](/docs/arvo/eyre/data-types#binding) & [$action](/docs/arvo/eyre/data-types#action) sections of the Data Types document for details).
135117
136−Example:
118+### Example
137119
138120```
139121> .^((list [binding:eyre duct action:eyre]) %e /=bindings=)
@@ -150,22 +132,22 @@ Example:
150132]
151133```
152134
153−# `connections`
135+## `%connections`
154136
155−A scry with `bindings` in place of the `desk` in the `beak` will return all open HTTP connections that aren't fully complete. The type returned is a `(map duct outstanding-connection:eyre)` (see the [outstanding-connection](@/docs/arvo/eyre/data-types.md#outstanding-connection) section of the Data Types document for details).
137+A scry with `bindings` in place of the `desk` in the `beak` will return all open HTTP connections that aren't fully complete. The type returned is a `(map duct outstanding-connection:eyre)` (see the [$outstanding-connection](/docs/arvo/eyre/data-types#outstanding-connection) section of the Data Types document for details).
156138
157−Example:
139+### Example
158140
159141```
160142> .^((map duct outstanding-connection:eyre) %e /=connections=)
161143{}
162144```
163145
164−# `authentication-state`
146+## `%authentication-state`
165147
166−A scry with `authentication-state` in place of the `desk` in the `beak` will return authentication details of all current sessions. The type returned is a [authentication-state](@/docs/arvo/eyre/data-types.md#authentication-state). The `p` field is the cookie sans the `urbauth-<ship>=` part.
148+A scry with `authentication-state` in place of the `desk` in the `beak` will return authentication details of all current sessions. The type returned is a [$authentication-state](/docs/arvo/eyre/data-types#authentication-state). The `p` field is the cookie sans the `urbauth-{SHIP}=` part.
167149
168−Example:
150+### Example
169151
170152```
171153> .^(authentication-state:eyre %e /=authentication-state=)
@@ -176,11 +158,11 @@ Example:
176158}
177159```
178160
179−# `channel-state`
161+## `%channel-state`
180162
181−A scry with `channel-state` in place of the `desk` in the `beak` will return details of the state of each channel. The type returned is a [channel-state](@/docs/arvo/eyre/data-types.md#channel-state).
163+A scry with `channel-state` in place of the `desk` in the `beak` will return details of the state of each channel. The type returned is a [channel-state](/docs/arvo/eyre/data-types#channel-state).
182164
183−Example:
165+### Example
184166
185167```
186168> .^(channel-state:eyre %e /=channel-state=)
@@ -201,11 +183,11 @@ Example:
201183]
202184```
203185
204−# `host`
186+## `%host`
205187
206188A scry with `host` in place of the `desk` in the `beak` will return host details of the ship. The type returned is a `hart:eyre`.
207189
208−Example:
190+### Example
209191
210192```
211193> .^(hart:eyre %e /=host=)
content/docs/arvo/eyre/tasks.md+43−60
@@ -4,30 +4,13 @@ weight = 3
44template = "doc.html"
55+++
66
7−# Contents
8−
9−- [Introduction](#introduction)
10−- [%live](#live) - _(Internal only)_ - Notifies Eyre of HTTP(S) ports.
11−- [%rule](#rule) - _(Usually internal)_ - Sets TLS cert or DNS binding.
12−- [%request](#request) - _(Internal only)_ - Incoming HTTP request.
13−- [%request-local](#request-local) - _(Internal only)_ - Incoming HTTP request from the local loopback port.
14−- [%cancel-request](#cancel-request) - _(Internal only)_ - Notifies Eyre of a connection being closed externally.
15−- [%connect](#connect) - Bind a Gall agent to a URL.
16−- [%serve](#serve) - Bind a generator to a URL.
17−- [%disconnect](#disconnect) - Disconnect agent or generator from URL binding.
18−- [%code-changed](#code-changed) - _(Usually internal)_ - Notifies Eyre of the web login code changing.
19−- [%approve-origin](#approve-origin) - Approve a CORS origin.
20−- [%reject-origin](#reject-origin) - Reject a CORS origin.
21−
22−# Introduction
23−
247This document details all the `task`s you're likely to use to interact with Eyre, as well as the `gift`s you'll receive in response.
258
26−The primary way of interacting with Eyre is from the outside with HTTP requests. As a result, most of its `task`s are only used internally and you're unlikely to need to deal with them directly. The ones you may want to use in certain cases are [%connect](#connect), [%serve](#serve), [%disconnect](#disconnect), [%approve-origin](#approve-origin) and [%reject-origin](#reject-origin), and they are also demonstrated in the [Examples](@/docs/arvo/eyre/examples.md) document. The rest are just documented for completeness.
9+The primary way of interacting with Eyre is from the outside with HTTP requests. As a result, most of its `task`s are only used internally and you're unlikely to need to deal with them directly. The ones you may want to use in certain cases are [%connect](#connect), [%serve](#serve), [%disconnect](#disconnect), [%approve-origin](#approve-origin) and [%reject-origin](#reject-origin), and they are also demonstrated in the [Examples](/docs/arvo/eyre/examples) document. The rest are just documented for completeness.
2710
28−Many of the types referenced are detailed in the [Data Types](@/docs/arvo/eyre/data-types.md) document. It may also be useful to look at the `+eyre` section of `/sys/lull.hoon` in Arvo where these `task`s, `gift`s and data structures are defined.
11+Many of the types referenced are detailed in the [Data Types](/docs/arvo/eyre/data-types) document. It may also be useful to look at the `+eyre` section of `/sys/lull.hoon` in Arvo where these `task`s, `gift`s and data structures are defined.
2912
30−# `%live`
13+## `%live`
3114
3215```hoon
3316[%live insecure=@ud secure=(unit @ud)]
@@ -37,11 +20,11 @@ This `task` notifies Eyre of the listening HTTPS and HTTP ports. It is automatic
3720
3821The `insecure` field is the HTTP port and `secure` is the optional HTTPS port.
3922
40−## Returns
23+### Returns
4124
4225Eyre returns no `gift` in response to a `%live` `task`.
4326
44−# `%rule`
27+## `%rule`
4528
4629```hoon
4730[%rule =http-rule]
@@ -49,13 +32,13 @@ Eyre returns no `gift` in response to a `%live` `task`.
4932
5033This `task` either configures HTTPS with a certificate and keypair, or configures a DNS binding. This is typically done for you by the `%acme` app, rather than done manually.
5134
52−The [http-rule](@/docs/arvo/eyre/data-types.md#http-rule) is either tagged with `%cert` or `%turf`. A `%cert` `http-rule` sets an HTTPS certificate and keypair or removes it if null. A `%turf` `http-rule` either adds or removes a DNS binding depending on whether the `action` is `%put` or `%del`. Note that using `%turf` will automatically cause the system to try and obtain a certificate and keypair via Letsencrypt.
35+The [$http-rule](/docs/arvo/eyre/data-types#http-rule) is either tagged with `%cert` or `%turf`. A `%cert` `http-rule` sets an HTTPS certificate and keypair or removes it if null. A `%turf` `http-rule` either adds or removes a DNS binding depending on whether the `action` is `%put` or `%del`. Note that using `%turf` will automatically cause the system to try and obtain a certificate and keypair via Letsencrypt.
5336
54−## Returns
37+### Returns
5538
5639Eyre returns no `gift` in response to a `%rule` `task`.
5740
58−# `%request`
41+## `%request`
5942
6043```hoon
6144[%request secure=? =address =request:http]
@@ -63,13 +46,13 @@ Eyre returns no `gift` in response to a `%rule` `task`.
6346
6447This `task` is how Eyre receives an inbound HTTP request. It will ordinarily be sent to Eyre by the runtime so you wouldn't use it except perhaps in tests.
6548
66−The `secure` field says whether it's over HTTPS. The `address` is the IP address from which the request originated. The [request:http](@/docs/arvo/eyre/data-types.md#request-http) is the HTTP request itself containing the method, URL, headers, and body.
49+The `secure` field says whether it's over HTTPS. The `address` is the IP address from which the request originated. The [$request:http](/docs/arvo/eyre/data-types#requesthttp) is the HTTP request itself containing the method, URL, headers, and body.
6750
68−## Returns
51+### Returns
6952
7053Eyre may `pass` a `%response` `gift` on the appropriate `duct` depending on the contents of the `%request`, state of the connection, and other factors.
7154
72−# `%request-local`
55+## `%request-local`
7356
7457```hoon
7558[%request-local secure=? =address =request:http]
@@ -77,11 +60,11 @@ Eyre may `pass` a `%response` `gift` on the appropriate `duct` depending on the
7760
7861This `task` is how Eyre receives an inbound HTTP request over the local loopback port. It behaves the same and takes the same arguments as in the [%request](#request) example except it skips any normally required authentication. Just like for a [%request](#request) `task`, you'd not normally use this manually.
7962
80−## Returns
63+### Returns
8164
8265Eyre may `pass` a `%response` `gift` on the appropriate `duct` depending on the contents of the `%request`, state of the connection, and other factors.
8366
84−# `%cancel-request`
67+## `%cancel-request`
8568
8669```hoon
8770[%cancel-request ~]
@@ -91,11 +74,11 @@ This `task` is sent to Eyre by the runtime when an HTTP client closes its previo
9174
9275This `task` takes no arguments.
9376
94−## Returns
77+### Returns
9578
9679Eyre may `pass` a `%response` `gift` on the appropriate `duct` depending on the state of the connection and other factors.
9780
98−# `%connect`
81+## `%connect`
9982
10083```hoon
10184[%connect =binding app=term]
@@ -103,19 +86,19 @@ Eyre may `pass` a `%response` `gift` on the appropriate `duct` depending on the
10386
10487This `task` binds a Gall agent to a URL path so it can receive HTTP requests and return HTTP responses directly.
10588
106−The [binding](@/docs/arvo/eyre/data-types.md#binding) contains a URL path and optional domain through which the agent will be able to take HTTP requests. The `app` is just the name of the Gall agent to bind. Note that if you bind a URL path of `/foo`, Eyre will also match `/foo/bar`, `/foo/bar/baz`, etc.
89+The [$binding](/docs/arvo/eyre/data-types#binding) contains a URL path and optional domain through which the agent will be able to take HTTP requests. The `app` is just the name of the Gall agent to bind. Note that if you bind a URL path of `/foo`, Eyre will also match `/foo/bar`, `/foo/bar/baz`, etc.
10790
108−If an agent is bound in Eyre using this method, HTTP requests to the bound URL path are poked directly into the agent. The `cage` in the poke have a `%handle-http-request` `mark` and a `vase` of `[@ta inbound-request:eyre]` where the `@ta` is a unique `eyre-id` and the [inbound-request](@/docs/arvo/eyre/data-types.md#inbound-request) contains the HTTP request itself.
91+If an agent is bound in Eyre using this method, HTTP requests to the bound URL path are poked directly into the agent. The `cage` in the poke have a `%handle-http-request` `mark` and a `vase` of `[@ta inbound-request:eyre]` where the `@ta` is a unique `eyre-id` and the [$inbound-request](/docs/arvo/eyre/data-types#inbound-request) contains the HTTP request itself.
10992
11093Along with the poke, Eyre will also subscribe to the `/http-response/[eyre-id]` `path` of the agent and await a response, which it will pass on to the HTTP client who made the request. Eyre expects at least two `fact`s and a `kick` on this subscription path to complete the response and close the connection (though it can take more than two `fact`s).
11194
112−The first `fact`'s `cage` must have a `mark` of `%http-response-header` and a `vase` containing a [response-header:http](@/docs/arvo/eyre/data-types.md#response-header-http) with the HTTP status code and headers of the response.
95+The first `fact`'s `cage` must have a `mark` of `%http-response-header` and a `vase` containing a [$response-header:http](/docs/arvo/eyre/data-types#response-headerhttp) with the HTTP status code and headers of the response.
11396
11497The `cage` of the second and subsequent `fact`s must have a `mark` of `%http-response-data` and a `vase` containing a `(unit octs)` with the actual data of the response. An `octs` is just `[p=@ud q=@]` where `p` is the byte-length of `q`, the data. You can send an arbitrary number of these.
11598
11699Finally, once you've sent all the `fact`s you want, you can `kick` Eyre's subscription and it will complete the response and close the connection to the HTTP client.
117100
118−## Returns
101+### Returns
119102
120103Eyre will respond with a `%bound` `gift` which says whether the binding was successful and looks like:
121104
@@ -125,11 +108,11 @@ Eyre will respond with a `%bound` `gift` which says whether the binding was succ
125108
126109The `accepted` field says whether the binding succeeded and the `binding` is the requested binding described above.
127110
128−## Example
111+### Example
129112
130−See the [Direct HTTP Handling With Gall Agents](@/docs/arvo/eyre/examples.md#direct-http-handling-with-gall-agents) section of the [Examples](@/docs/arvo/eyre/examples.md) document for an example.
113+See the [Direct HTTP Handling With Gall Agents](/docs/arvo/eyre/examples#direct-http-handling-with-gall-agents) section of the [Examples](/docs/arvo/eyre/examples) document for an example.
131114
132−# `%serve`
115+## `%serve`
133116
134117```hoon
135118[%serve =binding =generator]
@@ -137,9 +120,9 @@ See the [Direct HTTP Handling With Gall Agents](@/docs/arvo/eyre/examples.md#dir
137120
138121This `task` binds a generator to a URL path so it can receive HTTP requests and return HTTP responses.
139122
140−The `binding` contains the URL path and optional domain through which the generator will take HTTP requests. The [generator](@/docs/arvo/eyre/data-types.md#generator) specifies the `desk`, the `path` to the generator in Clay, and also has a field for arguments. Note that the passing of specified arguments to the generator by Eyre is not currently implemented, so you can just leave it as `~`.
123+The `binding` contains the URL path and optional domain through which the generator will take HTTP requests. The [$generator](/docs/arvo/eyre/data-types#generator) specifies the `desk`, the `path` to the generator in Clay, and also has a field for arguments. Note that the passing of specified arguments to the generator by Eyre is not currently implemented, so you can just leave it as `~`.
141124
142−The bound generator must be a gate within a gate and the type returned must be a [simple-payload:http](@/docs/arvo/eyre/data-types.md#simple-payload-http).
125+The bound generator must be a gate within a gate and the type returned must be a [$simple-payload:http](/docs/arvo/eyre/data-types#simple-payloadhttp).
143126
144127The sample of the first gate must be:
145128
@@ -153,19 +136,19 @@ The sample of the first gate must be:
153136[authenticated=? =request:http]
154137```
155138
156−The `?` says whether the HTTP request contained a valid session cookie and the [request:http](@/docs/arvo/eyre/data-types.md#request-http) contains the request itself.
139+The `?` says whether the HTTP request contained a valid session cookie and the [$request:http](/docs/arvo/eyre/data-types#requesthttp) contains the request itself.
157140
158141The `simple-payload:http` returned by the generator is similar to the response described in the [%connect](#connect) section except the HTTP headers and body are all contained in the one response rather than staggered across several.
159142
160−## Returns
143+### Returns
161144
162145Eyre will return a `%bound` `gift` as described at the end of the [%connect](#connect) section.
163146
164−## Example
147+### Example
165148
166−See the [Generators](@/docs/arvo/eyre/examples.md#generators) section of the [Examples](@/docs/arvo/eyre/examples.md) document for an example.
149+See the [Generators](/docs/arvo/eyre/examples#generators) section of the [Examples](/docs/arvo/eyre/examples) document for an example.
167150
168−# `%disconnect`
151+## `%disconnect`
169152
170153```hoon
171154[%disconnect =binding]
@@ -173,13 +156,13 @@ See the [Generators](@/docs/arvo/eyre/examples.md#generators) section of the [Ex
173156
174157This `task` deletes a URL binding previously set by a `%connect` or `%serve` `task`.
175158
176−The [binding](@/docs/arvo/eyre/data-types.md#binding) is the URL path and domain of the binding you want to delete.
159+The [$binding](/docs/arvo/eyre/data-types#binding) is the URL path and domain of the binding you want to delete.
177160
178−## Returns
161+### Returns
179162
180163Eyre returns no `gift` in response to a `%disconnect` `task`.
181164
182−# `%code-changed`
165+## `%code-changed`
183166
184167```hoon
185168[%code-changed ~]
@@ -189,11 +172,11 @@ This `task` tells Eyre that the web login code has changed, causing Eyre to thro
189172
190173This `task` takes no arguments.
191174
192−## Returns
175+### Returns
193176
194177Eyre returns no `gift` in response to a `%code-changed` `task`.
195178
196−# `%approve-origin`
179+## `%approve-origin`
197180
198181```hoon
199182[%approve-origin =origin]
@@ -201,17 +184,17 @@ Eyre returns no `gift` in response to a `%code-changed` `task`.
201184
202185This `task` tells Eyre to start responding positively to CORS requests for the specified `origin`.
203186
204−The [origin](@/docs/arvo/eyre/data-types.md#origin) is a CORS origin like `http://foo.example` you want to approve.
187+The [$origin](/docs/arvo/eyre/data-types#origin) is a CORS origin like `http://foo.example` you want to approve.
205188
206−## Returns
189+### Returns
207190
208191Eyre returns no `gift` in response to a `%approve-origin` `task`.
209192
210−## Example
193+### Example
211194
212−See the [Managing CORS Origins](@/docs/arvo/eyre/examples.md#managing-cors-origins) section of the [Examples](@/docs/arvo/eyre/examples.md) document for an example.
195+See the [Managing CORS Origins](/docs/arvo/eyre/examples#managing-cors-origins) section of the [Examples](/docs/arvo/eyre/examples) document for an example.
213196
214−# `%reject-origin`
197+## `%reject-origin`
215198
216199```hoon
217200[%reject-origin =origin]
@@ -219,12 +202,12 @@ See the [Managing CORS Origins](@/docs/arvo/eyre/examples.md#managing-cors-origi
219202
220203This `task` tells Eyre to start responding negatively to CORS requests for the specified `origin`.
221204
222−The [origin](@/docs/arvo/eyre/data-types.md#origin) is a CORS origin like `http://foo.example` you want want to reject.
205+The [$origin](/docs/arvo/eyre/data-types#origin) is a CORS origin like `http://foo.example` you want want to reject.
223206
224−## Returns
207+### Returns
225208
226209Eyre returns no `gift` in response to a `%reject-origin` `task`.
227210
228−## Example
211+### Example
229212
230−See the [Managing CORS Origins](@/docs/arvo/eyre/examples.md#managing-cors-origins) section of the [Examples](@/docs/arvo/eyre/examples.md) document for an example.
213+See the [Managing CORS Origins](/docs/arvo/eyre/examples#managing-cors-origins) section of the [Examples](/docs/arvo/eyre/examples) document for an example.
content/grants/urbit-http-api-for-python.mdnew file+43
@@ -0,0 +1,43 @@
1++++
2+title = "Urbit HTTP API for Python"
3+date = 2021-06-22
4+[taxonomies]
5+grant_type = ["Proposal"]
6+grant_category = ["App Dev: Other"]
7+[extra]
8+image = ""
9+description = "Write an Urbit HTTP API (aka airlock) for Python"
10+reward = 1
11+assignee = "novbyr-miclux"
12+id = "P0029"
13+completed = false
14+link = ""
15++++
16+
17+## Vision
18+
19+This proposed project will produce an API in Python language to interact with Urbit ship over HTTP with these [guidelines][airlock_requirements_link] in mind.
20+
21+[airlock_requirements_link]: https://docs.google.com/document/d/1no5oos_NE8LrUWz7iG9SKZMTIzruZVevZQ75nD5OHmI/edit
22+
23+## Design
24+
25+1. Basic HTTP Interface: Building a mechanism for sending and receiving JSON to/from an Urbit ship. The features in urlock-py will be integrated into this repository.
26+2. Graph Store Interface: Interaface to graph-store Urbit API.
27+3. Additional Agent Interfaces: Interface to the group-store and contact-store Gall agent.
28+
29+This will be done using the structure of [urbit http java api][urbit_http_api_java_link]
30+
31+[urbit_http_api_java_link]: https://github.com/ynx0/airlock
32+
33+## Me
34+
35+I have been programming in Python for 5+ years now. I have used Python for a wide range of tasks like scientific computing, machine learning, batch scripting etc. I am currently in the 4th year of my PhD program. I am also a contributor to an open source Python project UQpy as part of my PhD.
36+
37+## Milestones
38+
39+### Complete the API
40+
41+1 star
42+
43+A Github repository of the Python API complete with the proposed features, installation guide(README) will be developed and released.
lib/rss.js+4−6
@@ -24,17 +24,15 @@ const generateRSSFeed = () => {
2424 fs.readFileSync(path.join(dir, post.name)),
2525 options
2626 );
27+ const leadingDir = dir.substr(dir.indexOf("content") + 8);
28+ const name = post.name.replace(/.md$/, "");
29+
2730 return {
2831 title: pageData.title,
2932 descripton: pageData.description || "",
3033 author: pageData.extra.author || "",
3134 date: pageData.date,
32− link: path.join(
33− "https://urbit.org/",
34− dir.substr(dir.indexOf("content") + 7),
35− "/",
36− post.name.replace(/.md$/, "")
37− ),
35+ link: `https://urbit.org/${leadingDir}/${name}`,
3836 content: pageContent,
3937 };
4038 });
pages/community/[[...slug]].js+1
@@ -76,6 +76,7 @@ export default function UsingLayout({ posts, data, params, search, markdown }) {
7676 title={data.title}
7777 search={search}
7878 section={"Community"}
79+ params={params}
7980 >
8081 <div className={markdownStyles["markdown"]}>
8182 <article
pages/docs/[[...slug]].js+2−3
@@ -17,7 +17,6 @@ import ContentArea from "../../components/ContentArea";
1717import Sidebar from "../../components/Sidebar";
1818import markdownStyles from "../../styles/markdown.module.css";
1919import { decode } from "html-entities";
20−import { TableOfContents } from "../../components/TableOfContents";
2120
2221const breadcrumbs = (posts, paths) => {
2322 const results = [
@@ -88,7 +87,7 @@ const pageTree = (thisLink, tree, level = 0) => {
8887 <li>
8988 <Link href={href}>
9089 <a
91− className={`relative ${pageItemClasses} ${selectedClasses}`}
90+ className={`relative inline-block ${pageItemClasses} ${selectedClasses}`}
9291 >
9392 {title}
9493 </a>
@@ -144,6 +143,7 @@ export default function DocsLayout({
144143 title={data.title}
145144 search={search}
146145 section="Urbit Documentation"
146+ params={params}
147147 >
148148 <div className={markdownStyles["markdown"]}>
149149 <article
@@ -175,7 +175,6 @@ export default function DocsLayout({
175175 )}
176176 </div>
177177 </ContentArea>
178− <TableOfContents key={params.slug?.join("/") || "docs"} />
179178 </div>
180179 </>
181180 );
pages/getting-started/[[...slug]].js+1−2
@@ -7,7 +7,6 @@ import { join } from "path";
77import { buildPageTree, getPage } from "../../lib/lib";
88import Markdown from "../../components/Markdown";
99import ContentArea from "../../components/ContentArea";
10−import { TableOfContents } from "../../components/TableOfContents";
1110import Sidebar from "../../components/Sidebar";
1211import markdownStyles from "../../styles/markdown.module.css";
1312import { decode } from "html-entities";
@@ -94,6 +93,7 @@ export default function UsingLayout({ posts, data, params, search, markdown }) {
9493 title={data.title}
9594 search={search}
9695 section={"Getting Started"}
96+ params={params}
9797 >
9898 <div className={markdownStyles["markdown"]}>
9999 <article
@@ -101,7 +101,6 @@ export default function UsingLayout({ posts, data, params, search, markdown }) {
101101 ></article>
102102 </div>
103103 </ContentArea>
104− <TableOfContents key={params.slug?.join("/") || "getting-started"} />
105104 </div>
106105 </>
107106 );
pages/understanding-urbit/[[...slug]].js+19−1
@@ -36,7 +36,7 @@ const breadcrumbs = (posts, paths) => {
3636};
3737
3838const childPages = (thisLink, children, level = 0) => (
39− <ul className="pl-1">
39+ <ul>
4040 {children?.map((child) => (
4141 <li>{pageTree(join(thisLink, child.slug), child, level)}</li>
4242 ))}
@@ -74,6 +74,14 @@ export default function UnderstandingLayout({
7474 previousPost,
7575 nextPost,
7676}) {
77+ const router = useRouter();
78+ const isSelected = "/understanding-urbit".includes(router.asPath);
79+ const selectedClasses = classnames({
80+ dot: isSelected,
81+ "text-green": isSelected,
82+ "text-black": !isSelected,
83+ });
84+ const rootClasses = "pl-4 text-base hover:text-green";
7785 return (
7886 <>
7987 <Head>
@@ -82,6 +90,15 @@ export default function UnderstandingLayout({
8290 </Head>
8391 <div className="flex w-screen h-screen min-h-screen w-screen sidebar">
8492 <Sidebar search={search}>
93+ <ul>
94+ <li>
95+ <Link href="/understanding-urbit">
96+ <a className={`relative ${selectedClasses} ${rootClasses}`}>
97+ Introduction
98+ </a>
99+ </Link>
100+ </li>
101+ </ul>
85102 {childPages("/understanding-urbit", posts.pages)}
86103 </Sidebar>
87104 <ContentArea
@@ -89,6 +106,7 @@ export default function UnderstandingLayout({
89106 title={data.title}
90107 search={search}
91108 section={"Understanding Urbit"}
109+ params={params}
92110 >
93111 <div className={markdownStyles["markdown"]}>
94112 <article
pages/using/[[...slug]].js+1−2
@@ -8,7 +8,6 @@ import { join } from "path";
88import { getDocs, formatDate, buildPageTree, getPage } from "../../lib/lib";
99import Markdown from "../../components/Markdown";
1010import ContentArea from "../../components/ContentArea";
11−import { TableOfContents } from "../../components/TableOfContents";
1211import Sidebar from "../../components/Sidebar";
1312import markdownStyles from "../../styles/markdown.module.css";
1413import { decode } from "html-entities";
@@ -114,6 +113,7 @@ export default function UsingLayout({ posts, data, params, search, markdown }) {
114113 title={data.title}
115114 search={search}
116115 section={"Operator's Manual"}
116+ params={params}
117117 >
118118 <div className={markdownStyles["markdown"]}>
119119 <article
@@ -121,7 +121,6 @@ export default function UsingLayout({ posts, data, params, search, markdown }) {
121121 ></article>
122122 </div>
123123 </ContentArea>
124− <TableOfContents key={params.slug?.join("/") || "using"} />
125124 </div>
126125 </>
127126 );