on master help sign in
Merge commit '9f0f25551e2ebb6681162c2cb8795d02bc50de43' into urbit.org2
commit6c72986813687faf07a980538024a9ae4c1b87af authorMatilde Park <matilde@tlon.io> dateTue 27 Jul 2021, 20:21 (5 years ago) parent209b3b39f0f255
24 files changed+2597−1107
content/docs/_index.md+2−2 content/docs/arvo/ames/cryptography.md+145 content/docs/arvo/eyre/_index.md+18−3 content/docs/arvo/eyre/data-types.md+290 content/docs/arvo/eyre/examples.md+625 content/docs/arvo/eyre/external-api-ref.md+381 content/docs/arvo/eyre/eyre.md+28−688 content/docs/arvo/eyre/scry.md+213 content/docs/arvo/eyre/tasks.md+230 content/docs/arvo/eyre/using-eyre.md−230 content/docs/arvo/reference/_index.md+11 content/docs/arvo/reference/cryptography.md+222 content/docs/arvo/reference/filesystem.md+69 content/docs/azimuth/azimuth.md+7−8 content/docs/development/develop.md+2−2 content/docs/development/project-repositories.md+7−6 content/docs/hoon/reference/irregular.md+112−61 content/docs/system-overview/_index.md+13−13 content/docs/system-overview/cryptography.md+10−2 content/docs/userspace/gall/gall.md+88−89 content/docs/userspace/landscape/_index.md+1−1 content/docs/userspace/threads/http-api.md+73 content/docs/vere/_index.md+7−2 content/docs/vere/cryptography.md+43
content/docs/_index.md+2−2
@@ -12,14 +12,14 @@ welcome.
1212This documentation provides a series of explainers, guides, tutorials and
1313reference material for assisting you in developing on the Urbit platform, or
1414contributing to the Urbit project. If you're looking for documentation on how to
15−*use* your Urbit ship, see our [usage docs](/using/).
15+_use_ your Urbit ship, see our [usage docs](/using/).
1616
1717### [Development](/docs/development/)
1818
1919The Development section is recommended reading for developers interested in
2020contributing to Urbit itself, or building apps on top of Urbit. It serves as a
2121high-level orientation to how to set up a development environment, the various
22−codebases that comprise the project, our grants program, and the precepts that
22+codebases the project comprises, our grants program, and the precepts that
2323drive the development of Urbit.
2424
2525### [System Overview](/docs/system-overview/)
content/docs/arvo/ames/cryptography.mdnew file+145
@@ -0,0 +1,145 @@
1++++
2+title = "Cryptography"
3+weight = 5
4+template = "doc.html"
5++++
6+
7+Here we give a technical overview of how Ames implements cryptography.
8+
9+## Summary
10+
11+By default, all [packets are encrypted](#packets) with 256-bit
12+[AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) symmetric key
13+encryption, whose key is obtained by [Diffie-Hellman key exchange](#key-exchange),
14+with public/private keys generated using elliptic curve
15+[Curve25519](https://en.wikipedia.org/wiki/Curve25519). The only exception to
16+this are comet [self-attestation packets](#comets), which are unencrypted.
17+
18+All packets are also [signed](#packets) using [Elliptic Curve Digital Signature
19+Algorithm](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm).
20+
21+The `$ames-state` includes a [`+acru:ames`](#crypto-core) core, an interface
22+core into which one of the cryptosuites in `zuse` may be implemented. Some, but
23+not all, of the calls to cryptography-related tasks (encryption, signing,
24+decrypting, and authenticating) are peformed utilizing the `+acru` core.
25+
26+## Packet encryption and authentication {#packets}
27+
28+Each Urbit ship possesses two networking keypairs: one for encryption, and one
29+for authentication. We often refer to these two keypairs as though they were a
30+single keypair because they are stored as a single atom. [Elliptic Curve
31+Diffie-Hellman](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman)
32+is used for encryption, while [Elliptic Curve Digital Signature
33+Algorithm](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm)
34+is used for authentication
35+
36+The encrypted payload of each packet is a `$shut-packet`, which is the `+jam` of
37+a cell with the `bone`, message number, and message fragment or ack (see
38+[Ames](@/docs/arvo/ames/ames.md) for more information on packet structure). The
39+message fragment is signed using the authentication key. It is encrypted using
40+[`+en:crub:crypto`](@/docs/arvo/reference/cryptography.md#en) found in
41+`sys/zuse.hoon`, which utilizes the 256-bit AES-SIV algorithm.
42+
43+## Diffie-Hellman key exchange {#key-exchange}
44+
45+For each foreign ship a given ship has communicated with, `$ames-state` contains a
46+`$peer-state`, inside which the `$symmetric-key` (an atom which nests under
47+`@uw`) is utilized for encrypting all Ames packets shared between the two ships.
48+The `symmetric-key` is derived using [`+shar:ed:crypto`](@/docs/arvo/reference/cryptography.md#ed) found in `sys/zuse.hoon`,
49+which is an arm utilized for generating the symmetric key for elliptic curve
50+[Diffie-Hellman key
51+exchange](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange)
52+with [curve25519](https://en.wikipedia.org/wiki/Curve25519). Briefly, each ship
53+in a two-way conversation computes the shared symmetric key for that
54+conversation by computing the product of their own private key and the public
55+key of the other party.
56+
57+## Comet self-attestation {#comets}
58+
59+Recall that the `@p` of a comet is the hash of their 128-bit public key cast as
60+a `@p`. Since the public key of a comet is not stored on Azimuth, a comet proves
61+its identity with an "attestation packet". This is an unencrypted packet whose
62+payload is the comet's signature created with its private key. This is the only
63+circumstance under which a ship will send an unencrypted packet. The signature
64+is generated with
65+[`+sign:as:crub`](@/docs/arvo/reference/cryptography.md#sign-as) found in
66+`sys/zuse.hoon`.
67+
68+Upon hearing an attestation packet, the receiving ship will generate a symmetric
69+key for communications with the comet, according to the [key
70+exchange](#key-exchange) protocol.
71+
72+The fact that the first packet exchanged between a comet and another ship must
73+be an attestation packet is why comets are unable to initiate communication with
74+one another, and also why comets must be the first to initiate communication
75+with a non-comet. This is a technical limitation with a planned workaround.
76+
77+## `+acru:ames` {#crypto-core}
78+
79+The `+crypto-core` in `$ames-state` is an `+acru:ames` core, a
80+[lead](@/docs/hoon/reference/advanced.md#dry-polymorphism-and-core-nesting-rules)
81+interface core for asymmetric cryptosuites found in `sys/lull.hoon` which
82+handles encryption, decryption, signing, and verifying. In practice, the only
83+cryptosuite in use is [`+crub:crypto`](#crub), which implements [Suite B
84+Cryptography](https://en.wikipedia.org/wiki/NSA_Suite_B_Cryptography).
85+
86+```hoon
87+ ++ acru $_ ^? :: asym cryptosuite
88+ |% :: opaque object
89+ ++ as ^? :: asym ops
90+ |% ++ seal |~([a=pass b=@] *@) :: encrypt to a
91+ ++ sign |~(a=@ *@) :: certify as us
92+ ++ sure |~(a=@ *(unit @)) :: authenticate from us
93+ ++ tear |~([a=pass b=@] *(unit @)) :: accept from a
94+ -- ::as ::
95+ ++ de |~([a=@ b=@] *(unit @)) :: symmetric de, soft
96+ ++ dy |~([a=@ b=@] *@) :: symmetric de, hard
97+ ++ en |~([a=@ b=@] *@) :: symmetric en
98+ ++ ex ^? :: export
99+ |% ++ fig *@uvH :: fingerprint
100+ ++ pac *@uvG :: default passcode
101+ ++ pub *pass :: public key
102+ ++ sec *ring :: private key
103+ -- ::ex ::
104+ ++ nu ^? :: reconstructors
105+ |% ++ pit |~([a=@ b=@] ^?(..nu)) :: from [width seed]
106+ ++ nol |~(a=ring ^?(..nu)) :: from ring
107+ ++ com |~(a=pass ^?(..nu)) :: from pass
108+ -- ::nu ::
109+ -- ::acru ::
110+```
111+
112+As the `+acru` core is merely an interface, the details on how it is implemented
113+may vary according to the cryptosuite. We summarize what each
114+core is utilized for here, but see
115+[`crub:crypto`](@/docs/arvo/reference/cryptography.md#crub) for more details on
116+how the specific cryptosuite utilized by Ames is implemented.
117+
118+#### `+as:acru`
119+
120+This core is used for the standard asymmetric cryptographic operations: encrypting
121+(`+seal`), signing (`+sign`), authenticating (`+sure`), and decrypting (`+tear`).
122+
123+#### `+ex:acru`
124+
125+This core is used to extract keys and their fingerprints. `+sec` is the secret key (which
126+may be empty), `+pub` is the public key associated to the secret key, `+pac` is
127+the fingerprint associated to the secret key, and `+fig` is the fingerprint
128+associated to the public key. We note that when the core contains both
129+encryption and authentication keys, they are typically concatenated to be
130+returned as a single atom.
131+
132+#### `+nu:acru`
133+
134+This core contains constructors for the `+acru` core. `+pit:nu` is used to
135+construct an `+acru` core with both a private and public key (i.e. both
136+`+sec:ex` and `+pub:ex` are set) from a bitlength and seed. `+nol:nu` can then be
137+called from an `+acru` core created with `+pit:nu` to get an `+acru` core with
138+only the secret key, while `+com:nu` can be called to get an `+acru` core with
139+only the public key.
140+
141+#### `+en:acru`, `+de:acru`, and `+dy:acru`
142+
143+These arms are for symmetric encryption (`+en`) and decryption (`+de` and
144+`+dy`). The difference between the decryption arms is that `+de` returns null
145+and `+dy` crashes upon failure.
content/docs/arvo/eyre/_index.md+18−3
@@ -8,9 +8,24 @@ insert_anchor_links = "right"
88
99## [Overview](/docs/arvo/eyre/eyre)
1010
11−A high-level overview of `eyre`, Urbit's HTTP server vane.
11+An overview of Eyre and its capabilities.
1212
13−## [Using Eyre](/docs/arvo/eyre/using-eyre)
13+## [External API Reference](/docs/arvo/eyre/external-api-ref)
1414
15−How to use Urbit's HTTP API.
15+Details of Eyre's external API including the channel system's JSON API.
1616
17+## [Internal API Reference](@/docs/arvo/eyre/tasks.md)
18+
19+The `task`s Eyre takes and the `gift`s it returns.
20+
21+## [Scry Reference](@/docs/arvo/eyre/scry.md)
22+
23+The scry endpoints of Eyre.
24+
25+## [Data Types](@/docs/arvo/eyre/data-types.md)
26+
27+Reference documentation of the various data types used by Eyre.
28+
29+## [Examples](@/docs/arvo/eyre/examples.md)
30+
31+Practical examples of the different ways of using Eyre.
content/docs/arvo/eyre/data-types.mdnew file+290
@@ -0,0 +1,290 @@
1++++
2+title = "Data Types"
3+weight = 5
4+template = "doc.html"
5++++
6+
7+# Introduction
8+
9+This document describes the data types used by Eyre as defined in `/sys/lull.hoon`. It's separated into two sections:
10+
11+- [Eyre](#eyre) - Eyre-specific data types.
12+- [HTTP](#http) - HTTP data types shared between Eyre and Iris.
13+
14+# Eyre
15+
16+## `$origin`
17+
18+```hoon
19++$ origin @torigin
20+```
21+
22+A single CORS origin as used in an HTTP Origin header and the [$cors-registry](#cors-registry).
23+
24+## `$cors-registry`
25+
26+```hoon
27++$ cors-registry
28+ $: requests=(set origin)
29+ approved=(set origin)
30+ rejected=(set origin)
31+ ==
32+```
33+
34+CORS 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.
35+
36+## `$outstanding-connection`
37+
38+```hoon
39++$ outstanding-connection
40+ $: =action
41+ =inbound-request
42+ response-header=(unit response-header:http)
43+ bytes-sent=@ud
44+ ==
45+```
46+
47+An 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.
48+
49+## `$authentication-state`
50+
51+```hoon
52++$ authentication-state sessions=(map @uv session)
53+```
54+
55+This represents the authentication state of all sessions. It maps session cookies (without the `urbauth-<ship>=` prefix) to [$session](#session)s.
56+
57+## `$session`
58+
59+```hoon
60++$ session
61+ $: expiry-time=@da
62+ channels=(set @t)
63+ ==
64+```
65+
66+This 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.
67+
68+## `$channel-state`
69+
70+```hoon
71++$ channel-state
72+ $: session=(map @t channel)
73+ duct-to-key=(map duct @t)
74+ ==
75+```
76+
77+The 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.
78+
79+## `$timer`
80+
81+```hoon
82++$ timer
83+ $: date=@da
84+ =duct
85+ ==
86+```
87+
88+A 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.
89+
90+## `$channel-event`
91+
92+```hoon
93++$ channel-event
94+ $% $>(%poke-ack sign:agent:gall)
95+ $>(%watch-ack sign:agent:gall)
96+ $>(%kick sign:agent:gall)
97+ [%fact =mark =noun]
98+ ==
99+```
100+
101+An unacknowledged event in the channel system.
102+
103+## `$channel`
104+
105+```hoon
106++$ channel
107+ $: state=(each timer duct)
108+ next-id=@ud
109+ last-ack=@da
110+ events=(qeu [id=@ud request-id=@ud =channel-event])
111+ unacked=(map @ud @ud)
112+ subscriptions=(map @ud [ship=@p app=term =path duc=duct])
113+ heartbeat=(unit timer)
114+ ==
115+```
116+
117+This 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).
118+
119+## `$binding`
120+
121+```hoon
122++$ binding
123+ $: site=(unit @t)
124+ path=(list @t)
125+ ==
126+```
127+
128+A `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.
129+
130+## `$action`
131+
132+```hoon
133++$ action
134+ $% [%gen =generator] :: dispatch to a generator
135+ [%app app=term] :: dispatch to an application
136+ [%authentication ~] :: internal authentication page
137+ [%logout ~] :: internal logout page
138+ [%channel ~] :: gall channel system
139+ [%scry ~] :: gall scry endpoint
140+ [%four-oh-four ~] :: respond with the default file not found page
141+ ==
142+```
143+
144+The action to take when a [$binding](#binding) matches an incoming HTTP request.
145+
146+## `$generator`
147+
148+```hoon
149++$ generator
150+ $: =desk :: desk on current ship that contains the generator
151+ path=(list @t) :: path on :desk to the generator's hoon file
152+ args=* :: args: arguments passed to the gate
153+ ==
154+```
155+
156+This 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.
157+
158+## `$http-config`
159+
160+```hoon
161++$ http-config
162+ $: secure=(unit [key=wain cert=wain])
163+ proxy=_|
164+ log=?
165+ redirect=?
166+ ==
167+```
168+
169+The 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`.
170+
171+## `$http-rule`
172+
173+```hoon
174++$ http-rule
175+ $% [%cert cert=(unit [key=wain cert=wain])]
176+ [%turf action=?(%put %del) =turf]
177+ ==
178+```
179+
180+This 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.
181+
182+## `$address`
183+
184+```hoon
185++$ address
186+ $% [%ipv4 @if]
187+ [%ipv6 @is]
188+ ==
189+```
190+
191+A client IP address.
192+
193+## `$inbound-request`
194+
195+```hoon
196++$ inbound-request
197+ $: authenticated=?
198+ secure=?
199+ =address
200+ =request:http
201+ ==
202+```
203+
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.
205+
206+# HTTP
207+
208+## `$header-list:http`
209+
210+```hoon
211++$ header-list (list [key=@t value=@t])
212+```
213+
214+An 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`.
215+
216+## `$method:http`
217+
218+```hoon
219++$ method
220+ $? %'CONNECT'
221+ %'DELETE'
222+ %'GET'
223+ %'HEAD'
224+ %'OPTIONS'
225+ %'POST'
226+ %'PUT'
227+ %'TRACE'
228+ ==
229+```
230+
231+An HTTP method.
232+
233+## `$request:http`
234+
235+```hoon
236++$ request
237+ $: method=method
238+ url=@t
239+ =header-list
240+ body=(unit octs)
241+ ==
242+```
243+
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.
245+
246+## `$response-header:http`
247+
248+```hoon
249++$ response-header
250+ $: status-code=@ud
251+ headers=header-list
252+ ==
253+```
254+
255+The status code and [$header-list:http](#header-list-http) of an HTTP response.
256+
257+## `$http-event:http`
258+
259+```hoon
260++$ http-event
261+ $% $: %start
262+ =response-header
263+ data=(unit octs)
264+ complete=?
265+ ==
266+ $: %continue
267+ data=(unit octs)
268+ complete=?
269+ ==
270+ [%cancel ~]
271+ ==
272+```
273+
274+Packetized HTTP.
275+
276+Urbit treats Earth's HTTP servers as pipes, where Urbit sends or receives one or more `http-event`s. The first of these will be a `%start`, and the last will always be `%cancel` or will have `complete` set to `%.y` to finish the connection.
277+
278+Calculation 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.
279+
280+## `$simple-payload:http`
281+
282+```hoon
283++$ simple-payload
284+ $: =response-header
285+ data=(unit octs)
286+ ==
287+--
288+```
289+
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.
content/docs/arvo/eyre/examples.mdnew file+625
@@ -0,0 +1,625 @@
1++++
2+title = "Examples"
3+weight = 6
4+template = "doc.html"
5++++
6+
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+
19+This documents contains practical examples of the various ways of interacting with Eyre.
20+
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.
22+
23+# Authenticating
24+
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).
26+
27+Here we'll try authenticating with the default fakezod code.
28+
29+Using `curl` in the unix terminal, we'll make an HTTP POST request with `"password=<code>"` in the body:
30+
31+```
32+curl -i localhost:8080/~/login -X POST -d "password=lidlut-tabwed-pillex-ridrup"
33+```
34+
35+Eyre will respond with HTTP status 204, and a `set-cookie` header containing the session cookie.
36+
37+```
38+HTTP/1.1 204 ok
39+Date: Tue, 18 May 2021 01:38:48 GMT
40+Connection: keep-alive
41+Server: urbit/vere-1.5
42+set-cookie: urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm; Path=/; Max-Age=604800
43+```
44+
45+The `urbauth-....` cookie can be now be included in subsequent requests (e.g. to the channel system) by providing it in a Cookie HTTP header.
46+
47+# Using The Channel System
48+
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.
50+
51+First, 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.
52+
53+Now that we have our cookie, we can try poking an app & simultaneously opening a new channel. In this case, we'll poke the `hood` app with a `mark` of `helm-hi` to print "Opening airlock" in the dojo.
54+
55+We'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.
56+
57+The data will be a JSON array containing a [poke](@/docs/arvo/eyre/external-api-ref.md#poke) `action`:
58+
59+```
60+curl --header "Content-Type: application/json" \
61+ --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" \
62+ --request PUT \
63+ --data '[{"id":1,"action":"poke","ship":"zod","app":"hood","mark":"helm-hi","json":"Opening airlock"}]' \
64+ http://localhost:8080/~/channel/my-channel
65+```
66+
67+If we now have a look in the dojo we'll see it's printed our message, so the poke was successful:
68+
69+```
70+< ~zod: Opening airlock
71+```
72+
73+Now we can connect to the `mychannel` channel we opened. We do this with an HTTP GET request with our session cookie and the same path as the last request:
74+
75+```
76+curl -i --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" http://localhost:8080/~/channel/my-channel
77+```
78+
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:
80+
81+```
82+HTTP/1.1 200 ok
83+Date: Tue, 18 May 2021 01:40:47 GMT
84+Connection: keep-alive
85+Server: urbit/vere-1.5
86+set-cookie: urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm; Path=/; Max-Age=604800
87+connection: keep-alive
88+cache-control: no-cache
89+content-type: text/event-stream
90+transfer-encoding: chunked
91+
92+id: 0
93+data: {"ok":"ok","id":1,"response":"poke"}
94+```
95+
96+Normally this event stream would be handled by an EventSource object or similar in Javascript or the equivalent in whatever other language you're using. Here, though, we'll continue using `curl` for simplicity.
97+
98+Leaving 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.
99+
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`:
101+
102+```
103+curl --header "Content-Type: application/json" \
104+ --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" \
105+ --request PUT \
106+ --data '[{"id":2,"action":"subscribe","ship":"zod","app":"graph-store","path":"/updates"}]' \
107+ http://localhost:8080/~/channel/my-channel
108+```
109+
110+Notice 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.
111+
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:
113+
114+```
115+id: 1
116+data: {"ok":"ok","id":2,"response":"subscribe"}
117+```
118+
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`:
120+
121+```
122+id: 2
123+data: {"json":{"graph-update":{"add-graph":{"graph":{},"resource":{"name":"test-1183","ship":"zod"},"mark":"graph-validator-chat","overwrite":false}}},"id":2,"response":"diff"}
124+```
125+
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:
127+
128+```
129+curl --header "Content-Type: application/json" \
130+ --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" \
131+ --request PUT \
132+ --data '[{"id":3,"action":"ack","event-id":2}]' \
133+ http://localhost:8080/~/channel/my-channel
134+```
135+
136+This 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.
137+
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:
139+
140+```
141+curl --header "Content-Type: application/json" \
142+ --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" \
143+ --request PUT \
144+ --data '[{"id":4,"action":"unsubscribe","subscription":2}]' \
145+ http://localhost:8080/~/channel/my-channel
146+```
147+
148+Unlike `poke` and `subscribe` actions, Eyre doesn't acknowledge `unsubscribe`s, but we'll now have stopped receiving updates from `graph-store`.
149+
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`:
151+
152+```
153+curl --header "Content-Type: application/json" \
154+ --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" \
155+ --request PUT \
156+ --data '[{"id":5,"action":"delete"}]' \
157+ http://localhost:8080/~/channel/my-channel
158+```
159+
160+With our channel deleted, we can now close the connection on the client side.
161+
162+# Scrying
163+
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.
165+
166+First we must obtain a session cookie by [authenticating](#authenticating).
167+
168+Having obtained a cookie, we can now try a scry. We'll scry the `graph-store` Gall agent on the `/x/keys` scry path, which will return the list of channels it has. If you don't already have any chat channels on your fakezod, go ahead and create one via landscape so it'll have something to return.
169+
170+The url path will be `/~/scry/graph-store/keys.json`. The `/~/scry` part specifies a scry, the `/graph-store` part is the Gall agent, the `/keys` is the scry path without the `care`, and the `.json` file extension specifies the return `mark`.
171+
172+The request will be an HTTP GET request:
173+
174+```
175+curl -i --cookie "urbauth-~zod=0v1.1pseu.tq7hs.hps2t.ltaf1.tmqjm" \
176+ --request GET \
177+ http://localhost:8080/~/scry/graph-store/keys.json
178+```
179+
180+Eyre will respond with HTTP status 200 if it's successful and the body of the response will contain the data we requested:
181+
182+```
183+HTTP/1.1 200 ok
184+Date: Fri, 04 Jun 2021 10:16:32 GMT
185+Connection: keep-alive
186+Content-Length: 61
187+Server: urbit/vere-1.5
188+set-cookie: urbauth-~zod=0v1.1pseu.tq7hs.hps2t.ltaf1.tmqjm; Path=/; Max-Age=604800
189+content-type: application/json
190+
191+{"graph-update":{"keys":[{"name":"test-1183","ship":"zod"}]}}
192+```
193+
194+Now let's make a request to a non-existent scry endpoint:
195+
196+```
197+curl -i --cookie "urbauth-~zod=0v1.1pseu.tq7hs.hps2t.ltaf1.tmqjm" \
198+ --request GET \
199+ http://localhost:8080/~/scry/foo/bar/baz.json
200+```
201+
202+Eyre will respond with a 404 Missing status and an error message:
203+
204+```
205+HTTP/1.1 404 missing
206+Date: Fri, 04 Jun 2021 10:22:51 GMT
207+Connection: keep-alive
208+Content-Length: 187
209+Server: urbit/vere-1.5
210+set-cookie: urbauth-~zod=0v1.1pseu.tq7hs.hps2t.ltaf1.tmqjm; Path=/; Max-Age=604800
211+content-type: text/html
212+
213+<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>
214+```
215+
216+# Direct HTTP Handling With Gall Agents
217+
218+In 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.
219+
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.
221+
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.
223+
224+Note 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.
225+
226+`eyre-agent.hoon`
227+
228+```hoon
229+/+ default-agent, dbug
230+=* card card:agent:gall
231+%- agent:dbug
232+^- agent:gall
233+|_ =bowl:gall
234++* this .
235+ def ~(. (default-agent this %|) bowl)
236+::
237+++ on-init on-init:def
238+++ on-save on-save:def
239+++ on-load on-load:def
240+++ on-poke
241+ |= [=mark =vase]
242+ ^- (quip card _this)
243+ ?+ mark
244+ (on-poke:def [mark vase])
245+ ::
246+ %noun
247+ ?. =(q.vase %bind)
248+ %- (slog leaf+"Bad argument." ~)
249+ `this
250+ %- (slog leaf+"Attempting to bind /foo." ~)
251+ :_ this
252+ [%pass /bind-foo %arvo %e %connect `/'foo' %eyre-agent]~
253+ ::
254+ %handle-http-request
255+ =/ req !< (pair @ta inbound-request:eyre) vase
256+ ~& [mark req]
257+ ?+ method.request.q.req
258+ =/ data=octs
259+ (as-octs:mimes:html '<h1>405 Method Not Allowed</h1>')
260+ =/ content-length=@t
261+ (crip ((d-co:co 1) p.data))
262+ =/ =response-header:http
263+ :- 405
264+ :~ ['Content-Length' content-length]
265+ ['Content-Type' 'text/html']
266+ ['Allow' 'GET']
267+ ==
268+ :_ this
269+ :~
270+ [%give %fact [/http-response/[p.req]]~ %http-response-header !>(response-header)]
271+ [%give %fact [/http-response/[p.req]]~ %http-response-data !>(`data)]
272+ [%give %kick [/http-response/[p.req]]~ ~]
273+ ==
274+ ::
275+ %'GET'
276+ =/ data=octs
277+ (as-octs:mimes:html '<h1>Hello, World!</h1>')
278+ =/ content-length=@t
279+ (crip ((d-co:co 1) p.data))
280+ =/ =response-header:http
281+ :- 200
282+ :~ ['Content-Length' content-length]
283+ ['Content-Type' 'text/html']
284+ ==
285+ :_ this
286+ :~
287+ [%give %fact [/http-response/[p.req]]~ %http-response-header !>(response-header)]
288+ [%give %fact [/http-response/[p.req]]~ %http-response-data !>(`data)]
289+ [%give %kick [/http-response/[p.req]]~ ~]
290+ ==
291+ ==
292+ ==
293+++ on-watch
294+ |= =path
295+ ^- (quip card _this)
296+ ?+ path
297+ (on-watch:def path)
298+ ::
299+ [%http-response *]
300+ %- (slog leaf+"Eyre subscribed to {(spud path)}." ~)
301+ `this
302+ ==
303+++ on-leave on-leave:def
304+++ on-peek on-peek:def
305+++ on-agent on-agent:def
306+++ on-arvo
307+ |= [=wire =sign-arvo]
308+ ^- (quip card _this)
309+ ?. ?=([%bind-foo ~] wire)
310+ (on-arvo:def [wire sign-arvo])
311+ ?> ?=([%eyre %bound *] sign-arvo)
312+ ?: accepted.sign-arvo
313+ %- (slog leaf+"/foo bound successfully!" ~)
314+ `this
315+ %- (slog leaf+"Binding /foo failed!" ~)
316+ `this
317+++ on-fail on-fail:def
318+--
319+```
320+
321+Save the above to `/app/eyre-agent.hoon`. Commit it:
322+
323+```
324+> |commit %home
325+>=
326++ /~zod/home/2/app/eyre-agent/hoon
327+```
328+
329+...and start it:
330+
331+```
332+> |start %eyre-agent
333+>=
334+gall: loading %eyre-agent
335+activated app home/eyre-agent
336+[unlinked from [p=~zod q=%eyre-agent]]
337+```
338+
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`:
340+
341+```hoon
342+ %noun
343+?. =(q.vase %bind)
344+ %- (slog leaf+"Bad argument." ~)
345+ `this
346+%- (slog leaf+"Attempting to bind /foo." ~)
347+:_ this
348+[%pass /eyre %arvo %e %connect `/'foo' %eyre-agent]~
349+```
350+
351+...and when `%eyre` responds with a `%bound` `gift`, the `+on-agent` arm will print whether the bind succeeded:
352+
353+```hoon
354+ [%eyre %bound *]
355+?: accepted.sign-arvo
356+ %- (slog leaf+"/foo bound successfully!" ~)
357+ `this
358+%- (slog leaf+"Binding /foo failed!" ~)
359+`this
360+```
361+
362+...so let's try:
363+
364+```
365+> :eyre-agent %bind
366+>=
367+Attempting to bind /foo.
368+/foo bound successfully!
369+```
370+
371+As you can see, we have successfully bound the `/foo` url path. Now we can try making an HTTP request. Over in the unix terminal, we can make a GET request using curl:
372+
373+```
374+> curl -i localhost:8080/foo
375+HTTP/1.1 200 ok
376+Date: Mon, 17 May 2021 04:39:40 GMT
377+Connection: keep-alive
378+Server: urbit/vere-1.5
379+Content-Type: text/html
380+Content-Length: 22
381+transfer-encoding: chunked
382+
383+<h1>Hello, World!</h1>%
384+```
385+
386+...which has succeed! This is because the `+on-poke` arm tests for http GET requests and responds with `Hello, World!` when it sees one:
387+
388+```hoon
389+ %'GET'
390+=/ data=octs
391+ (as-octs:mimes:html '<h1>Hello, World!</h1>')
392+=/ content-length=@t
393+ (crip ((d-co:co 1) p.data))
394+=/ =response-header:http
395+ :- 200
396+ :~ ['Content-Length' content-length]
397+ ['Content-Type' 'text/html']
398+ ==
399+:_ this
400+:~
401+ [%give %fact [/http-response/[p.req]]~ %http-response-header !>(response-header)]
402+ [%give %fact [/http-response/[p.req]]~ %http-response-data !>(`data)]
403+ [%give %kick [/http-response/[p.req]]~ ~]
404+==
405+```
406+
407+Back in the dojo, our app's `+on-watch` arm has printed the path on which Eyre has subscribed for the response:
408+
409+```
410+Eyre subscribed to /http-response/~.eyre_0v3.1knjk.l544e.5uds6.fn9l2.f8929.
411+```
412+
413+...and it's also printed the request so you can see how it looks when it comes in:
414+
415+```
416+[ %handle-http-request
417+ p=~.~.eyre_0v3.1knjk.l544e.5uds6.fn9l2.f8929
418+ q
419+ [ authenticated=%.n
420+ secure=%.n
421+ address=[%ipv4 .127.0.0.1]
422+ request
423+ [ method=%'GET'
424+ url='/foo'
425+ header-list
426+ ~[
427+ [key='host' value='localhost:8080']
428+ [key='user-agent' value='curl/7.76.1']
429+ [key='accept' value='*/*']
430+ ]
431+ body=~
432+ ]
433+ ]
434+]
435+```
436+
437+This is a very rudimentary app but it demonstrates the basic mechanics of dealing with HTTP requests and serving responses.
438+
439+# Generators
440+
441+Here 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.
442+
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.
444+
445+Here'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`.
446+
447+Note that this example does some 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.
448+
449+`eyre-gen.hoon`
450+
451+```hoon
452+|= [[now=@da eny=@uvJ bec=beak] ~ ~]
453+|= [authenticated=? =request:http]
454+^- simple-payload:http
455+=/ msg=@t
456+ ?~ body.request
457+ (scot %da now)
458+ (cat 3 (cat 3 (scot %da now) 10) q.u.body.request)
459+=/ data=octs
460+ (as-octs:mimes:html msg)
461+=/ =response-header:http
462+ [200 ['Content-Type' 'text/plain']~]
463+[response-header `data]
464+```
465+
466+Eyre requires generators to be a gate within a gate. The sample of the first gate must be:
467+
468+```hoon
469+[[now=@da eny=@uvJ bec=beak] ~ ~]
470+```
471+
472+The sample of the second nested gate must be:
473+
474+```hoon
475+[authenticated=? =request:http]
476+```
477+
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.
479+
480+Because generators return the entire HTTP message as a single `simple-payload`, Eyre can calculate the `content-length` itself and automatically add the header.
481+
482+In order to make our generator available, we must bind it to a URL path. To do this, we send Eyre a `%serve` `task`, which looks like:
483+
484+```hoon
485+[%serve =binding =generator]
486+```
487+
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.
489+
490+Let's bind our generator to the `/mygen` URL path with the `|pass` command in the dojo:
491+
492+```
493+|pass [%e [%serve `/mygen %home /gen/eyre-gen/hoon ~]]
494+```
495+
496+Note that Eyre responds with a `%bound` `gift` to indicate whether the binding succeeded but `|pass` doesn't take such responses so it's not shown.
497+
498+Now let's try making an HTTP request using `curl` in the unix terminal:
499+
500+```
501+curl -i http://localhost:8080/mygen --data 'blah blah blah'
502+```
503+
504+We can see that the request has succeeded and our generator has responded with the datetime and request body:
505+
506+```
507+HTTP/1.1 200 ok
508+Date: Sat, 29 May 2021 09:19:45 GMT
509+Connection: keep-alive
510+Content-Length: 41
511+Server: urbit/vere-1.5
512+Content-Type: text/plain
513+Content-Length: 41
514+
515+~2021.5.29..09.19.45..e096
516+blah blah blah
517+```
518+
519+# Managing CORS Origins
520+
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.
522+
523+In 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.
524+
525+First, using `|pass` in the dojo, let's approve the origin `http://foo.example` by sending Eyre a `%approve-origin` `task`:
526+
527+```
528+|pass [%e [%approve-origin 'http://foo.example']]
529+```
530+
531+Now if we scry for the [approved](@/docs/arvo/eyre/scry.md#cors-approved) CORS `set`:
532+
533+```
534+> .^(approved=(set @t) %ex /=//=/cors/approved)
535+approved={'http://foo.example'}
536+```
537+
538+...we can see that `http://foo.example` has been added.
539+
540+Next, let's test it by sending Eyre a CORS preflight request via `curl` in unix:
541+
542+```
543+curl -i -X OPTIONS \
544+ -H "Access-Control-Request-Method: POST" \
545+ -H "Access-Control-Request-Headers: X-Requested-With" \
546+ -H "Origin: http://foo.example" \
547+ http://localhost:8080
548+```
549+
550+We can see in the response that it has succeeded:
551+
552+```
553+HTTP/1.1 204 ok
554+Date: Fri, 28 May 2021 12:37:12 GMT
555+Connection: keep-alive
556+Server: urbit/vere-1.5
557+Access-Control-Allow-Origin: http://foo.example
558+Access-Control-Allow-Credentials: true
559+Access-Control-Allow-Headers: X-Requested-With
560+Access-Control-Allow-Methods: POST
561+```
562+
563+Now we'll try rejecting an `origin`. Back in the dojo, let's `|pass` Eyre a `%reject-origin` `task` for `http://bar.example`:
564+
565+```
566+|pass [%e [%reject-origin 'http://bar.example']]
567+```
568+
569+If we scry for the [rejected](@/docs/arvo/eyre/scry.md#cors-rejected) CORS `set`:
570+
571+```
572+> .^(rejected=(set @t) %ex /=//=/cors/rejected)
573+rejected={'http://bar.example'}
574+```
575+
576+...we can see that `http://bar.example` has been added.
577+
578+If we again test it with `curl` in unix:
579+
580+```
581+curl -i -X OPTIONS \
582+ -H "Access-Control-Request-Method: POST" \
583+ -H "Access-Control-Request-Headers: X-Requested-With" \
584+ -H "Origin: http://bar.example" \
585+ http://localhost:8080
586+```
587+
588+...we can see that, as expected, it has not returned the access control headers:
589+
590+```
591+HTTP/1.1 404 missing
592+Date: Fri, 28 May 2021 12:38:47 GMT
593+Connection: close
594+Server: urbit/vere-1.5
595+```
596+
597+Finally, let's look at CORS requests that are neither approved nor rejected.
598+
599+If we make another request with `curl` on unix, this time for `http://baz.example` which we haven't added to a list:
600+
601+```
602+curl -i -X OPTIONS \
603+ -H "Access-Control-Request-Method: POST" \
604+ -H "Access-Control-Request-Headers: X-Requested-With" \
605+ -H "Origin: http://baz.example" \
606+ http://localhost:8080
607+```
608+
609+...we can see it also correctly fails to return the access control headers:
610+
611+```
612+HTTP/1.1 404 missing
613+Date: Fri, 28 May 2021 12:39:59 GMT
614+Connection: close
615+Server: urbit/vere-1.5
616+```
617+
618+Now if we scry for the [requests](@/docs/arvo/eyre/scry.md#cors-requests) CORS `set`:
619+
620+```
621+> .^(requests=(set @t) %ex /=//=/cors/requests)
622+requests={'http://baz.example' 'http://localhost:8080'}
623+```
624+
625+... we can see it has automatically been added by the mere fact of the request being made.
content/docs/arvo/eyre/external-api-ref.mdnew file+381
@@ -0,0 +1,381 @@
1++++
2+title = "External API Reference"
3+weight = 2
4+template = "doc.html"
5++++
6+
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
32+
33+To use Eyre's channel system, run threads or perform scries you must first obtain a session cookie by authenticating with the following HTTP request:
34+
35+| HTTP Method | Data | URL Path | Notes |
36+| ----------- | -------------------------------------- | ---------- | ----------------------------------------------------------------------------------- |
37+| `POST` | `password=lidlut-tabwed-pillex-ridrup` | `/~/login` | The password is your web login code which can be obtained with `+code` in the dojo. |
38+
39+See the [examples](@/docs/arvo/eyre/examples.md#authenticating) for an example of how to do this using the curl.
40+
41+Eyre's response will include a `set-cookie` header like:
42+
43+```
44+set-cookie: urbauth-~zod=0v4.ilskp.psv00.t09r0.l8rps.3n97v; Path=/; Max-Age=604800
45+```
46+
47+The `urbauth-{...}` cookie provided must be included in a `cookie` header with all subsequent requests like:
48+
49+```
50+cookie: urbauth-~zod=0v4.ilskp.psv00.t09r0.l8rps.3n97v
51+```
52+
53+# Channels
54+
55+Eyre's channel system is the primary way of interacting with Gall agents from outside of Urbit.
56+
57+Data from an external HTTP client is sent to Eyre as an [HTTP PUT request](#http-requests) containing one or more [action](#actions) JSON objects. Clients must obtain a session cookie by [authenticating](#authentication) with Eyre in order to make such requests.
58+
59+Data from Eyre is sent back to the external HTTP client on a channel as SSEs ([Server Sent Events](https://html.spec.whatwg.org/#server-sent-events)) containing a [response](#responses) JSON object.
60+
61+A new channel is automatically created whenever a client sends an [action](#action) in an [HTTP PUT request](#http-requests) to `http{s}://{host}{port}/~/channel/{uid}` with a new `uid`. To connect to the channel and receive any pending events, you just send an HTTP GET request with a valid session cookie to that URL.
62+
63+The response you'll get to the GET request will be an event stream. Events will come in like:
64+
65+```
66+id: 0
67+data: {"ok":"ok","id":1,"response":"poke"}
68+```
69+
70+If you're working with Javascript in the browser context you'll handle these with an EventSource object or by using fetch and ReadableStream. If you're using another language, there'll likely be a library available to handle SSEs.
71+
72+All the events that Eyre sends you on a channel must be [ack](#ack)ed so that Eyre can forget about them and clear them from the channel state. If `fact`s (as [diff](#diff)s) from Gall agents to which you've subscribed are left un`ack`ed long enough, Eyre will consider the particular subscription clogged and automatically unsubscribe you. Note that `ack`ing one event will implicitly `ack` all previous events.
73+
74+When you're finished with a channel, you can send Eyre a [delete action](#delete-channel) to close it.
75+
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.
77+
78+## HTTP Requests
79+
80+[Actions](#actions) are sent to Eyre in HTTP PUT requests:
81+
82+| HTTP Method | Required Headers | Data | URL Path |
83+| ----------- | ------------------------- | -------------------------------------------------------------- | ------------------ |
84+| `PUT` | `Content-Type` & `Cookie` | One or more [actions](#actions) wrapped in a JSON array (`[]`) | `/~/channel/{uid}` |
85+
86+The `cookie` header contains the session cookie obtained by [authenticating](#authentication). The data is a JSON array containing one or more JSON [action](#actions) objects. The channel `uid` is a unique name of your choosing. Typically you'd use the current unix time and a hash but there's no specific requirements. If you're opening a new channel you'd choose a new `uid` and if you already have a channel open you'd just use that.
87+
88+If successful, Eyre will respond with a status code of 204. Note the HTTP response will have no content, any [responses](#responses) will be sent as SSEs on the channel event stream.
89+
90+## Actions
91+
92+### Poke
93+
94+This is for poking a Gall agent.
95+
96+| Key | JSON Type | Example Value | Description |
97+| -------- | --------- | ------------- | ------------------------------------------------------------- |
98+| `id` | Number | `1` | ID for keeping track of sent messages. |
99+| `action` | String | `'poke'` | The kind of action. |
100+| `ship` | String | `'zod'` | Target ship name, excluding leading `~`. |
101+| `app` | String | `'hood'` | Name of the gall agent you're poking. |
102+| `mark` | String | `'helm-hi'` | Type of data. Must correspond to a mark definition in `/mar`. |
103+| `json` | Any | `'hello'` | Actual payload. Any JSON type, determined by app. |
104+
105+**Example**
106+
107+```json
108+{
109+ "id": 1,
110+ "action": "poke",
111+ "ship": "zod",
112+ "app": "hood",
113+ "mark": "helm-hi",
114+ "json": "hello"
115+}
116+```
117+
118+**Response**
119+
120+Eyre will send a [poke ack](#poke-ack) as an SSE event on the channel event stream.
121+
122+### Subscribe
123+
124+This is for subscribing to a watch `path` of a Gall agent.
125+
126+| Key | JSON Type | Example Value | Description |
127+| -------- | --------- | --------------- | --------------------------------------------------- |
128+| `id` | Number | `2` | ID for keeping track of sent messages. |
129+| `action` | String | `'subscribe'` | The kind of action. |
130+| `ship` | String | `'zod'` | Target ship name, excluding leading `~`. |
131+| `app` | String | `'graph-store'` | Name of the gall agent to which you're subscribing. |
132+| `path` | String | `'/updates'` | The path to watch. Depends on the app. |
133+
134+**Example**
135+
136+```json
137+{
138+ "id": 2,
139+ "action": "subscribe",
140+ "ship": "zod",
141+ "app": "graph-store",
142+ "path": "/updates"
143+}
144+```
145+
146+**Response**
147+
148+Eyre 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`.
149+
150+### Ack
151+
152+This is for acknowledging an SSE event. If you `ack` one event, you also implicitly `ack` all previous events. Events _must_ be `ack`ed so that Eyre can forget them. If you leave `fact`s (as [diff](#diff)s) un`ack`ed long enough, Eyre will consider the subscription clogged and automatically unsubscribe you.
153+
154+| Key | JSON Type | Example Value | Description |
155+| ---------- | --------- | ------------- | -------------------------------------------------------- |
156+| `id` | Number | `3` | ID for keeping track of sent messages. |
157+| `action` | String | `'ack'` | The kind of action. |
158+| `event-id` | Number | `7` | ID of SSE event up to which you're acknowledging receipt |
159+
160+**Example**
161+
162+```json
163+{
164+ "id": 3,
165+ "action": "ack",
166+ "event-id": 7
167+}
168+```
169+
170+**Response**
171+
172+Eyre will not respond to an `ack` action.
173+
174+### Unsubscribe
175+
176+This is for unsubscribing from a Gall agent watch `path` to which you've previously subscribed.
177+
178+| Key | JSON Type | Example Value | Description |
179+| -------------- | --------- | ------------- | ---------------------------------------------------------- |
180+| `id` | Number | `4` | ID for keeping track of sent messages. |
181+| `action` | String | `unsubscribe` | The kind of action. |
182+| `subscription` | Number | `2` | Request ID of the initial `subscribe` action from earlier. |
183+
184+**Example**
185+
186+```json
187+{
188+ "id": 4,
189+ "action": "unsubscribe",
190+ "subscription": 2
191+}
192+```
193+
194+**Response**
195+
196+Eyre will not respond to an `unsubscribe` action.
197+
198+### Delete Channel
199+
200+This is for deleting the channel itself.
201+
202+| Key | JSON Type | Example Value | Description |
203+| -------- | --------- | ------------- | -------------------------------------- |
204+| `id` | Number | `5` | ID for keeping track of sent messages. |
205+| `action` | String | `'delete'` | The kind of action. |
206+
207+**Example**
208+
209+```json
210+{
211+ "id": 5,
212+ "action": "delete"
213+}
214+```
215+
216+**Response**
217+
218+Eyre will not respond to a `delete` action.
219+
220+## Responses
221+
222+### Poke Ack
223+
224+This 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.
225+
226+**Positive Poke Ack**
227+
228+| Key | JSON Type | Example Value | Description |
229+| ---------- | --------- | ------------- | -------------------------------------------- |
230+| `ok` | String | `'ok'` | Positive acknowledgement. |
231+| `id` | Number | `1` | Request ID of the `poke` being acknowledged. |
232+| `response` | String | `'poke'` | The kind of action being acknowledged. |
233+
234+**Example**
235+
236+```json
237+{
238+ "ok": "ok",
239+ "id": 1,
240+ "response": "poke"
241+}
242+```
243+
244+**Negative Poke Ack**
245+
246+| Key | JSON Type | Example Value | Description |
247+| ---------- | --------- | ---------------- | --------------------------------------------------------------------- |
248+| `err` | String | `'some text...'` | Negative acknowledgement. Contains an error message and/or traceback. |
249+| `id` | Number | `1` | Request ID of the `poke` being acknowledged. |
250+| `response` | String | `'poke'` | The kind of action being acknowledged. |
251+
252+**Example**
253+
254+```json
255+{
256+ "err": "<error message and traceback>",
257+ "id": 1,
258+ "response": "poke"
259+}
260+```
261+
262+**Action Required**
263+
264+You must ack the event.
265+
266+### Watch Ack
267+
268+This 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.
269+
270+**Positive Watch Ack**
271+
272+| Key | JSON Type | Example Value | Description |
273+| ---------- | --------- | ------------- | --------------------------------------------- |
274+| `ok` | String | `'ok'` | Positive acknowledgement. |
275+| `id` | Number | `2` | Request ID of the initial `subscribe` action. |
276+| `response` | String | `'subscribe'` | The kind of action being acknowledged. |
277+
278+**Example**
279+
280+```json
281+{
282+ "ok": "ok",
283+ "id": 2,
284+ "response": "subscribe"
285+}
286+```
287+
288+**Negative Watch Ack**
289+
290+| Key | JSON Type | Example Value | Description |
291+| ---------- | --------- | ---------------- | --------------------------------------------------------------------- |
292+| `err` | String | `'some text...'` | Negative acknowledgement. Contains an error message and/or traceback. |
293+| `id` | Number | `2` | Request ID of the initial `subscribe` action. |
294+| `response` | String | `'subscribe'` | The kind of action being acknowledged. |
295+
296+**Example**
297+
298+```json
299+{
300+ "err": "<error message and traceback>",
301+ "id": 2,
302+ "response": "subscribe"
303+}
304+```
305+
306+**Action Required**
307+
308+You must ack the event.
309+
310+### Diff
311+
312+All `fact`s sent by a Gall agent on the `path` to which you've subscribed are delivered as `diff`s. Note that Eyre makes a best effort to convert the `fact` to a `json` mark. If it can't, Eyre will crash and close the subscription, and you won't receive any `diff` for the `fact`.
313+
314+| Key | JSON Type | Example Value | Description |
315+| ---------- | --------- | ---------------- | ------------------------------------------------------------ |
316+| `json` | Any | `{'foo': 'bar'}` | The actual data from the agent, could be any JSON structure. |
317+| `id` | Number | `3` | Request ID of the initial `subscribe` action from earlier. |
318+| `response` | String | `'diff'` | The kind of response. All `fact`s are marked `'diff'`. |
319+
320+**Example**
321+
322+```json
323+{
324+ "json": { "foo": "bar" },
325+ "id": 3,
326+ "response": "diff"
327+}
328+```
329+
330+**Action Required**
331+
332+You must [ack](#ack) each `diff` that comes in the event stream.
333+
334+### Quit
335+
336+A `quit` comes in when a subscription has been ended. You may be intentionally kicked by the Gall agent to which you're subscribed, but certain network conditions can also trigger a `quit`. As a result, it's best to try and re[subscribe](#subscribe) when you get a `quit`, and if the resulting [watch ack](#watch-ack) is negative you can then conclude the `quit` was intentional and give up.
337+
338+| Key | JSON Type | Example Value | Description |
339+| ---------- | --------- | ------------- | --------------------------------------------- |
340+| `id` | Number | `4` | Request ID of the initial `subscribe` action. |
341+| `response` | String | `'quit'` | The kind of response. |
342+
343+**Example**
344+
345+```json
346+{
347+ "id": 4,
348+ "response": "quit"
349+}
350+```
351+
352+**Action Required**
353+
354+You must ack the event and you may wish to try and re[subscribe](#subscribe).
355+
356+# Scry
357+
358+A scry is a read-only request for some data.
359+
360+A scry takes the form of an [authenticated](#authentication) HTTP GET request to a URL path with the following format:
361+
362+```
363+http{s}://{host}/~/scry/{app}{path}.{mark}
364+```
365+
366+The `{app}` is the name of the Gall agent you want to query, for example `graph-store`.
367+
368+The `{path}` is a scry endpoint of the Gall agent in question. Eyre will always scry with a care of `%x`, so the `{path}` needn't specify that. For example, the `/x/keys` scry endpoint of `graph-store` would just be specified as `keys`.
369+
370+The `{mark}` is the type you want returned. It needn't just be `json` as with the channel system, it can be any `mark`, with two conditions:
371+
372+1. It must be possible to convert the `mark` produced by the specified scry endpoint to the `mark` you want returned.
373+2. It must be possible to convert the `mark` you want returned to a `mime` `mark`, otherwise Eyre can't encode it in the HTTP response.
374+
375+If 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.
376+
377+See the [Scrying](@/docs/arvo/eyre/examples.md#scrying) section of the [Examples](@/docs/arvo/eyre/examples.md) document for a practical example.
378+
379+# Spider
380+
381+See the [HTTP API](@/docs/userspace/threads/http-api.md) section of the [Threads](@/docs/userspace/threads/overview.md) documentation.
content/docs/arvo/eyre/eyre.md+28−688
@@ -2,720 +2,60 @@
22title = "Overview"
33weight = 1
44template = "doc.html"
5−aliases = ["/docs/learn/arvo/eyre/"]
65+++
76
8−*Current docs on Eyre are out of date. Until they are updated this doc remains for historical purposes*
7+Eyre is the webserver vane.
98
9+HTTP 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−Our HTTP server.
11+# Authentication
1212
13−Unix sends http messages to `%eyre`, and `%eyre` produces http messages
14−in response. In general, apps and vanes do not call `%eyre`; rather,
15−`%eyre` calls apps and vanes. `%eyre` uses `%ford` and `%gall` to
16−functionally publish pages and facilitate communication with apps.
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.
1714
18−`%eyre` primarily parses web requests and handles them in a variety of
19−ways, depending on the control string. Nearly all of these are
20−essentially stateless, like functional publishing with `%ford`.
21−Additionally, there's a fairly significant component that handles
22−`%gall` messaging and subscriptions, which must be stateful.
15+# The Channel System
2316
24−## Reference
17+Eyre'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.
2518
26−### State
19+The 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.
2720
28−Stored
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.
2922
30−- `++bolo`
31−- `++cyst`
32−- `++stem`
23+# Scrying
3324
34−Runtime
25+Along 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.
3526
36−- `perk`
37− + `perk-auth`
38−- `pest`
39−- `even`
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.
4028
41−### Cores
29+# Spider Threads
4230
43−- `++handle`
44− + `++parse`
45− - `++as...`
46−- `++ya`
47−- `++ix`
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.
4832
49−## Commentary
33+# Generators
5034
35+Generators, 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.
5136
52−Let us follow the loading of a simple cli app, as it bounces from
53−browser to server to browser and back.
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.
5438
55−### Initial request
39+# Direct HTTP Handling With Gall Agents
5640
57−An http request for `http://sampel-sipnym.urbit.org/cli` will be [redirected](dns)
58−to the `%eyre` on ~sampel-sipnym, and come in as a `%this` task.
41+As 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.
5942
60−From arvo, requests enter `++call`, which after some type reification are passed
61−along to `++apex:ye`. In the case of a `%this` task, its components are
62−parsed(see `++zest:epur`, `++eat-headers`) and handed off to `++handle`, wrapped
63−in `++emule` to produce a `++fail` page in case of error. `++apex:handle` will
64−`++process` the request to a `pest` or a `++done` [core](/docs/glossary/core/), and in the former case
65−`++resolve` the pest into an outgoing card.
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.
6644
67−XX it also seems to affect the current ship, test that serving ship name is consistently correct
45+# Cross-Origin Resource Sharing
6846
69−The pest is produced by `++process`, which will first further `++parse` the
70−request, and if this does not make the response immediately obvious,
71−`++process-parsed` the resulting `perk`.
47+Eyre 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.
7248
73−`++parse` produces the `perk`, by attempting to interpret the `pork`(url path)
74−[`++as-magic-filename`](#mage), `++as-beam`, and `++as-aux-request`. In this
75−case, `/cli` is parsed by the second case as a `%beam` query to `/=cli=`: a path
76−which starts with a valid ship name is expected to be a full clay(well, ford)
77−path, and one starting with a term implies the current serving ship and a case
78−of `0`, the current revision.
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.
7950
80−XX spur: when the desks are merged, `/cli` shall point to `/=main=/pub/cli`
51+# Eyre Documentation Sections
8152
82−The parsed `perk` generates a `%f %boil` note, `mark`ed as its extension(here
83−defaulting to `%urb`) and `wire`d with `~` to return unaltered to the client. It
84−goes on to `++resolve` by being passed to `++ford-get-beam`, which translates
85−the perk it into a `%boil` `++ford-req`, adding an `++fcgi` path-segment
86−containing query string and `++fcgi-cred:for-client` auth information.
53+- [External API Reference](@/docs/arvo/eyre/external-api-ref.md) - Details of Eyre's external API including the channel system's JSON API.
8754
88−`%ford`s translation of `/=cli=/hymn/hook` to a self-refreshing `%urb` html page
89−[deserves its own commentary](/docs/arvo/ford#commentary), but
90−we resume in `%eyre` when the `%made` sign arrives in `++take`, and soon after
91−`++axon:ye`. There the `wire`, or rather the `whir` it has been verified to be,
92−determines that the response should be served immediately. However, as the mark
93−is not `%mime`, another trip to `%ford` is required to encode it, on the same
94−wire; afterwards, the value of the `%mime` cage is verified to be of the correct type, and finally
95−delivered back up the requesting duct as a successful `%thou` HTTP response.
55+- [Internal API Reference](@/docs/arvo/eyre/tasks.md) - The `task`s Eyre takes and the `gift`s it returns.
9656
97−XX `%cast %mime` used to be in ford-get-beam, is there a reason it was removed?
57+- [Scry Reference](@/docs/arvo/eyre/scry.md) - The scry endpoints of Eyre.
9858
99−## Back into the breach, or: auxilary requests
59+- [Data Types](@/docs/arvo/eyre/data-types.md) - Reference documentation of the various data types used by Eyre.
10060
101−Now, it was mentioned that this result is self-refreshing: the `%urb`
102−translation [door](/docs/glossary/door/) injects a `;script@"/~/on/{deps}.js"` into every page, `deps`
103−is a ford-readable hash of the set of resources that page construction depended
104−on.
105−
106−This triggers another `%this` request. Its handling is identical to that of
107−`/cli` up until `++parse`, where it is seen not `++as-beam` but
108−`++as-aux-request`(auxillary requests starting with `/~/` or `/~~/`).
109−`/on/[hash]` is a long-`%poll`, which `++process-parsed`, for a `.js` mark,
110−answers with a direct `%js`. Its contents are the static `++poll:js`, which
111−initiates the long-polling loop, run against an injected `urb.js` of
112−`{poll:[hash]}`.
113−
114−A `%js` `pest` is `resolve`d as a `text/javascript` success `%this`.
115−
116−When `poll.js` is received by the client, it opens an `XMLHttpRequest` for
117−`/~/on/{window.urb.poll}.json`, bringing us back to `%poll:process`.
118−
119−In the case of a non-`%js` `/~/on/`, `%poll:process-parsed` turns into a
120−`++new-dependency`, which stores the listening duct, and `pass-note`s a `%wasp`
121−with the deps-hash back to `%ford` whence it came. While this occured, the page
122−has loaded.
123−
124−Some indeterminate amount of time afterwards, with dropped `/~/on/{...}.json`s
125−being retried upon expiring and also being stored, a `%news` sign arrives in
126−`++axon`, and the hash in question is retrieved from the wire, and the listening
127−long-polls retrieved by the hash. Each receives a 205 "Reload parent view" HTTP
128−response, which `poll.js` dutifully executes, and a fixed typo of markdown is
129−rendered.
130−
131−## Authentication
132−
133−Now, while this accurately reflects the presentation of e.g. a markdown file,
134−`/cli` is an application front-end, and one that permits only owner access. Its
135−second script is `@"/~~/~/at/main/lib/urb.js"`, semantically equivalent to
136−`/~/as/own/~/at/main/lib/urb.js`, and handled as follows.
137−
138−In `++as-aux-request`, `%as %own` becomes `%auth %get our` perk, which
139−`++process` passes to `++process-parsed` passes to `++process-auth`. There, a
140−`yac` "ya" core is built `++for-client`: a `++cookie-prefix`, which is just the
141−serving ship name, is used to get a `++session-from-cookies`, here nil as the
142−client has no cookie set. In lieu of a cookie, a `++new-ya` is constructed, with
143−a random token `hole` and a `++new-cyst` which fills out `cyst` session state
144−from request data.
145−
146−Returning to `++process-auth`, `%get` checks if the yac is authenticated with
147−the requested credentials(`anon` requests are always granted), which for the
148−fresh new `cyst` is not the case (more on success [later](#auth-ok)). Unless
149−authenticating as a [foreign ship](#xeno), the only thing left is to
150−`++show-login-page`, which detects that the requested resource is not `%html`,
151−and produces a `%red` pest. For `%js`, `%red`irections `++resolve` to
152−`++auth-redir:js`, a line of javascript which prepends `/~~` to the url path.
153−
154−The owner-authenticated main page request similarly ends in `++show-login-page`,
155−which for the empty session is an `[%htme ++login-page:xml]`, `resolve`d to
156−`++give-html` with a 401 "unathorized".
157−
158−The login page shows a simple prompt, and requests `/~/at/auth.js` to handle the
159−submission. And so we are, once again, attempting to divine if what we're doing
160−makes sense `++as-aux-request`.
161−
162−To understand `/~/at`, there will first be a brief diversion to `~/auth.json`.
163−`auth.json`, perk `[%auth %json]`, in `++process-auth` serves `++stat-json:ya`,
164−containing such information as the serving ship, which identities are associated
165−with this session, and `oryx`, a CSRF token. An oryx must be present on all
166−stateful requests, in this case executing a log in. It also saves the new/old
167−session using `abet`.
168−
169−XX explain `ixor` here and not [later](#ixor)?
170−
171−`/~/at` is an alternate interface, which injects `auth.json` data into the
172−requested file. `/~/at/auth.js`, then, is a request for the built-in `auth:js`
173−(parsed to and processed from an `[%auth %js ~]` perk), with session data added
174−as `window.urb`. And indeed, ``[`%js /~/at/auth]`` is parsed to
175−``[%auth at [`%js /auth]``, which in `++process-auth` is re-`process`ed to
176−`[%js ++auth:js]`, which is `++resolve`d after an `++add-json` of
177−the relevant data. The yac cookies are also passed to `resolve`, which
178−`++add-cookies` injects into the `httr`.
179−
180−It is at this point that there is first occasion for user input, namely the password.
181−
182−The `auth:js` script sends a `PUT` request, also to `/~/auth.json`. In `parse`,
183−the first nontrivial `++check-oryx` occurs, `++grab-body` the request oryx and
184−ensuring it is recorded for the session. The request parsed with `++need-body`
185−to a `[%auth %try {password}]` perk. `%get:process-auth` checks it against
186−`++load-secret`, upon success updates the session with `++logon:ya`, and
187−serves a fresh `auth.json` which reflects the changed `user`. Upon receiving
188−this, the page is refreshed to retry the original request.
189−
190−### Post-authentication: app communication.
191−
192−Upon refresh, `/~~/cli` brings us for the third time to `%get:process-auth`, but
193−this time the cookie is set, and the `yac` fetched contains the serving ship as
194−authenticated. The `++handle` sample is updated to reflect the requesting ship,
195−and the `process` continues for the rest of the pork, once again serving the
196−ford page.
197−
198−The `/~/on/[deps].json` poll starts anew, and `/~~/~/at/main/lib/urb.js` we now
199−know to serve the window.urb necessary to make requests, and the `urb.js`
200−standard library which extends it with a number of wrappers to them and other
201−useful functions.
202−
203−One of those functions is `urb.bind`, which is used to subscribe to application
204−data. Userspace javascript sets `urb.appl` to `/tic`, and binds `lines` to a
205−`;pre;` text display, using a callback.
206−
207−This triggers a `PUT` to `/~/is/{ixor}/cli/lines.json`, where `ixor` is a hash
208−of `oryx` that identifies the connection. `++as-aux-request`, an `%is` is a
209−`%subs` subscription update update, which for `%put` forwards to
210−`++add-subs:ix`, the ix core fetched `++for-view` by hashing the request
211−`++oryx-to-ixor`.
212−
213−A view has all the state associated with a client that must be
214−remembered between events. In this case, this is what app/path the request duct
215−is associated with; but mainly, `++add-subs:ix` will `pass-note` to `%gall` so
216−it `%show`s the data on the path, current and future.
217−
218−This will immediately(assuming the ship is local) result in a `%nice` by the
219−`/cli` app, returning `{ok:true}` `++nice-json` to `urb.bind`'s second callback
220−as `{ok:true}`. The initial `%rush` results also arrive, and in `++axon` are
221−converted to json using `++back`(ford `%cast` wrapper), and when `%made` get
222−passed to `++get-rush:ix`. There the source application/path are decoded by
223−duct, and then the full event goes to `++get-even`; `++add-even` inserts it to
224−the queue, and as there is no long poll it simply stays there.
225−
226−Upon receipt, the client realizes the long-poll isn't actually running, so that
227−is started using `urb.poll`. At `/~/of/{ixor}`, perk
228−`[%view ixor ~ {sequence-number}]`, it is `process`ed by `++poll:ix` (the cyst
229−is retrieved by `++ire-ix` form global state, using the perk `ixor`): the
230−sequence number is in the past, so the previously received `%rush` is
231−`++give-even`. After deleting the previous message in the queue and invoking
232−`++pass-took` to signal `%gall` of this occurrence, the data is annotated with
233−the source app+path `++subs-to-json`, and returned to the polling duct.
234−
235−On the client, the user callback receives the `/cli` history, and displays it on
236−the page. The `/~/of` long poll is continued, this time reaching `++poll:ix`
237−with the "pending" sequence number, and being stored in the `cyst` for its troubles.
238−
239−Its next update proceeds idenitcally, but first it must be triggered, which
240−happens when the user enters "(add 2 2)\n", firing an `urb.send` from the event
241−handler. This sends a `POST` request to `/~/to/cli/json.json`, perk `%mess`,
242−`++process`ed to a `%g %mess`. Were the mark not `%json`, a `%ford` conversion
243−would occur first, and `%made:axon` would send the gall message proper. In
244−either case, eventually a `%mean` or `%nice` arrives, is encoded as json, and
245−sent to the client callback.
246−
247−## A path not taken: magic filenames
248−
249−The `/robots.txt` and `/favicon.(ico|png)` files are static, and served
250−immediately when caught by a `++parse`.
251−
252−XX index.html?
253−
254−## A path not taken: foreign auth
255−
256−While this example details a login `/~/as/own`, it is possible to be
257−authenticated as any ship on the network. A request for such seen in
258−`%get:process-auth` is passed to `++foreign-auth:ya`, which sends an
259−`%ames /lon` message to the ship in question. The foreign ship stores the
260−inquiry, calculates(the local) `++our-host` and responds with a `/hat`,
261−containing the redirection host, which is stored by `++foreign-hat`; it is later
262−used to send the client to a `/~/am` url on the foreign client, which acts as a
263−normal login page but later sends the client back. XX expand, basically the
264−status quo is you're logged in and `/~/as/foo` is ignored, just setting your
265−`urb.user` XX
266−
267−
268−### A path not taken: deauthentication
269−
270−`/~/away`, perk `[%away ~]`, produces a static `++logout-page:xml`, which also
271−uses `/~/at/auth.js`, to send a `DELETE /~/auth.json`, perk `[%auth %del]`. This
272−executes `++logoff:ya` for the cookie session, resolving to `++abut` to wipe it
273−from memory.
274−
275−### A path not taken: unsubscription
276−
277−`DELETE /~/is/app/path/within` works much like `PUT /~/is/app/path/within`,
278−`++del-subs:ix` acting as reverse of `++add-subs` by deleting the duct binding
279−and sending `%g %nuke`.
280−
281−
282−XX unmentioned arms: abet, add-poll, adit, ames-gram, anon, ares-to-json, bolo, cyst, doze, even, ford-kill, get-mean, gift, give-json, give-thou, gram, hapt, hasp, host-to-ship, ix, ixor, js, kiss, load, mean-json, move, note, pass-note, perk, perk-auth, pest, poke-test, print-subs, render-tang, resp, root-beak, scry, ses-authed, ses-ya, sign, silk, sine, stay, stem, teba, titl, to-oryx, urb, wait-era, wake, whir, wush, xml, ya, ye
283−
284−### Appendix A: DNS
285−
286−The `*.urbit.org` domain can be used to access destroyers and cruisers. In the
287−common case oh hosted ships, this is done by dynamic DNS directly to the hosting
288−instance. We do not speak of the uncommon case. When ports are blocked and
289−infrastructure crumbles around you, only imported martian networking can be
290−trusted: the `%get` and `%got` grams are used to proxy `%this` requests and
291−`%thou` responses respectively.
292−
293−## Specification
294−
295−The `%eyre` vane serves one purpose: receiving inbound HTTP requests from browsers and clients pretending to be browsers. To facilitate this communication, `%eyre` does two things: 1. provide an API for traditional clients to talk to; and 2. provide a mechanism for saving state that allows the server to keep track of identities/sessions, subscription data, and active connections.
296−
297−This document outlines the following:
298−
299−1. [`perk`](#perk), a `pork` subset that defines what URLs the client can send to `%eyre`.
300−
301−2. [the values stored on the client](#client), both statically in cookies and dynamically as the `window.urb` object, which facilitate this transaction.
302−
303−3. [`task`](#task), the requests `%eyre` will accept.
304−
305−4. [`gift`](#gift), the responses it will give to those requests.
306−
307−5. [`note`](#note), the set of arvo requests that %eyre makes to the other vanes.
308−
309−6. [`whir`](#whir), a `wire` subset, the associated dynamic state
310−
311−7. [`sign`](#sign), the responses `%eyre` accepts
312−
313−8. [`bolo`](#bolo), the state stored between separate events.
314−
315−## 1. URL structure
316−
317−There exist several URL forms accepted by `%eyre`.
318−
319−### 1.1 Functional request
320−
321−The simplest of them is a static `%f` functional publish request:
322−
323−```
324− GET /[ship]/[desk]/[case]/path/to/file.[mark]
325−```
326−e.g.
327−
328−```
329− /~pittyp-pittyp/main/5/lib/urb.js
330−```
331−A `case` of 0 signifies the most recent version.
332−
333−If no file extension is provided, the default `mark` is `%urb`, which consists of `%html` injected with an auto-refresh script.
334−
335−A shorter form:
336−
337−```
338− /path/to.[mark]
339−```
340−is prepended with the [default request path](#prefix). For example, if `%eyre`
341−is configured with a root of `/<our>/main/0/pub`, then `/doc/arvo` is
342−interpreted as a request for `/=main=/pub/doc/arvo.urb`.
343−
344−Auxiliary paths start with `/~/`, and provide other functionality, such as:
345−
346−### 1.2 Auto-reload
347−
348−When a new version of a page becomes available, it is useful to propagate it to the client. The `%f` vane manages the particulars, and provides an update token along with all published pages. The `/~/on` long-polling endpoint makes use of that token, which is a hash of the server-stored dependency set.
349−- `/~/on/[hash].json` retuns `true` when a page may require updating.
350−- `/~/on/[hash].js` is a lightweight script that polls for the above. It is primarily used in error messages.
351−
352−### 1.3 Authentication
353−
354−Authenticated requests are accomplished through sessions, tracked with cookies which are set on the first such request.
355−- `/~/as/[user]/...` is an authenticated request to `...`, where `user` can be a `@p` ship, `'own'`, `'any'`, or `'anon'`.
356− + `'anon'` is a randomly-generated per-session submarine, and requires no further authentication.
357− + `'own'` represents the serving ship. The short form of `/~/as/own/` is `/~~/`
358− + `'any'` requires a network ship, chosen with a prompt if unknown. The short form of `/~/as/any/` is `/_/`
359− + Auth requests are handled in three ways:
360− + I. If the session is associated with the `ship`, serve `...`, storing the ship as the session's default ship. For example, `/~/as/sivtyv-barnel/main/pub/test.html` is an authenticated request of `/main/pub/test.html` with the identity of `~sivtyv-barnel`.
361− + II. If the session is not associated with the `ship` in the path, the client is redirected to a login page, where a password can be entered. Successful authentication results in a page refresh to the requested path.
362− + III. otherwise, [send a message](#foreign) to the claimed ship, and redirect the user to `https://[foreign-host]/~/am/[ses]/...#[current-host]&?code=[code]`
363−- `/~/am/[ses]/...#original-host` similarly serves a login page. Upon success, inform the `ship` of the success and redirect it back to `http://[original-host]/~/as/<this-ship>/...`
364−- `/~/away.html` is a log-out page.
365−- `/~/auth.json` returns `{ship,oryx,user,auth}`: the serving ship, a CSRF token, active user, and all allowed users respectively.
366−- `/~/at/{...}.js` is an alternate form of `/~/auth.json`, which injects a line into the served js file that sets `{ship, oryx, user, auth}` on the `window.urb` object.
367−
368−So far, all the paths specified have been GET requests. Authentication, however, requires sending data. This is also done at the `/~/auth.json` endpoint.
369−- `POST {oryx,ship,code} /~/auth.json?PUT` is used by the login script to authorize a user, and returns the same result as `GET`, additionally containing either`{ok:true}` or `{fail:'type',mess:"Error message"}`
370−- `POST {oryx,ship?} /~/auth.json?DELETE` revokes authorization. Response as above.
371−
372−### 1.4 Messaging
373−
374−- `POST {oryx, wire, xyro} /~/to/[app]/[mark].json`, where `xyro` is data that will be converted to the `mark`. In the simplest case, `/~/to/hello/json.json` will pass `xyro` through verbatim, sending `[%json xyro]` to the `++poke` arm of app `%hello`.
375−- `POST {oryx, wire, xyro} /~/to/<ship>/[app]/[mark].json` is a foreign message send, as above.
376−
377−### 1.5 Subscriptions
378−
379−- `/~/of/[ixor]` is an `EventSource`: a conceptually infinite file containing a stream of events. By default, it sends a newline every 30 seconds serving to signal that the connection is alive to both the server and IP middleware.
380− + `/~/of/[ixor]?poll={n}` is a long-polling fallback interface. Produces event number `{n}`, blocking until it occurs. Its contexts can be affected by `POST` requests with a body of `{oryx, wire}`, and a query string of `PUT` or `DELETE`. They return either `{mark}`(which may be `null`), or [`{fail, mess}`](#mean-json)
381−- `/~/in/[hash].json` is a dual to [`/~/on`](#on-change). It binds `mod` events, which echo the requesting token.
382−- `/~/is/[app]/path/to.[mark]` binds `rush` events, formatted with a first line of `[app] /path/to`, and the rest containing subscription data. Additionally, `mean` events formatted similarly may arrive, also converted to the relevant mark.
383−
384−
385−
386−### 1.6 Ablative
387−
388−These interfaces will temporarily exist to aid development, and are to be considered unstable.
389−- `/~/debug/...` access normally inaccessible pages. For example, `/~/debug/as.html` will present the login page, regardless of current session status.
390−
391−
392−## 2. Client state
393−
394−Some information is stored on, and provided to, browser clients
395−
396−### 2.1 Cookies
397−
398−Authenticated users receive a cookie on the domain of `*.urbit.org`. The cookie contains a client session token, keyed by the serving ship.
399−
400−### 2.2 Authentication
401−
402−It is common(e.g. by the `%urb` mark) to set window.urb to the contents of `/~/auth.json`:
403−- `ship` is the serving ship
404−- `oryx` is a unique CSRF token that identifies this view, bound to the session cookie
405−- `ixor` is a hash of `oryx`, used as an insecure view identifier
406−- `user` is the authenticated/generated ship name
407−- `auth` is a list of identities usable by this session
408−
409−### 2.3 Client library
410−
411−To this object, `/main/lib/urb.js` adds helpers:
412−- `app` is an optional app name to send messages to by default
413−- `send({data,mark?='json',app?=urb.app,ship?}, cb?)` delivers messages
414−- `bind({path,app?=urb.app}, cb)` subscribes by path
415−- `drop({path,app?=urb.app}, cb?)` pulls the subscription
416−- `util` is an object containing methods for converting between JavaScript types and Hoon [atom](/docs/glossary/atom/) auras.
417−
418−## 3. Requests
419−
420−## `[%born port=@ud]`, unix init
421−
422−When the `vere` process is re/started, a TCP port is bound, HTTP requests on which are the scope of this document. The `%born` gift informs eyre of this occurrence, which in turn updates [its state.](#bolo)
423−
424−**Gifts given in response:** none.
425−
426−## `[%hiss p=mark q=cage]`, outbound http
427−
428−Userspace http request, converted by `%ford` into an actual `hiss`.
429−
430−**Gifts given in response:** a `%sigh`
431−
432−### 3.1 `[%this httq]`, inbound http
433−
434−The primary `%eyre` request type comes from the host system, and constitutes an inbound http request. It consists of five parts:
435−
436−I. `p=[? @if]`: a loobean determining whether the request is being made over https, and the client source, an IPv6 address possibly encoding an IPv4 one as `.0.0.0.0.0.ffff.wwxx.yyzz`
437−
438−II. `q=meth`, an http method
439−
440−III. `r=@t`, the unparsed URL
441−
442−IV. `s=mess`, an associative list of header keys/values
443−
444−V. `t=(unit octs)`, the request body, if any.
445−
446−After `r` is parsed to a `purl`, the `pork`(relative path) determines the resource being served. The first step in handling an http request is [classifying its intent](#perk).
447−
448−- A ford request results in a [`%boil` note](#boil).
449−- `/~/[name].js` is generated from [session](#sink) or [view](#stem) state, and [served](#mime) as `%js`.
450−- `/~/am` generates a login page.
451−- `/~/as` is resolved further if authenticated, generates a similar login page if the claimed ship is local, and otherwise is saved to [session state](#sink) and sends a ["login" `%a` message](#lon) to the foreign ship.
452−- `/~/at` and `/~/auth.json` generate a new `oryx` and store it in the [session state](#sink).
453−- `/~/in` and `/~/is` affect [view state](#stem), possibly sending subscriptions or unsubscriptions to `%f` and `%g` respectively, and are generated from view state.
454−- `/~/on` is saved to the `bolo` by `hash`, and translated to a [`%wasp` note](#wasp).
455−- `/~/of` fails if the `ixor` is unknown, and otherwise is stored in the `ixor`, receiving a partial response and all events after its [last-seen header](#). If it has a `poll` parameter, the response is full, and only occurs if the body is non-empty. Otherwise the oryx is saved as a [live](#live) request in case of cancellation.
456−- `/~/to` transforms into a [`%g` message](#mess).
457−
458−**Gifts given in response:** a `%thou`, or a [`%that`](#that) followed by multiple `%thar`s.
459−
460−### 3.2 `[%thud ~]`, inbound close
461−
462−Sent when an unresponded-to request is cancelled. The [live](#live) effect of the request is looked up, and
463−- `%exec` ford boil requests are cancelled with `[%exec ~]`
464−- `%wasp` ford deps requests are cancelled with `[%wasp |]`
465−- `%poll` session polls `%rest` the session heartbeat timeout
466−
467−### 3.3 `[%thin p=@ud]`, delivery failure
468−
469−Sent when a partial [response](#that) or [body](#thar) fails to arrive. Its `duct` is the same as that of the original request. This is handled by [waiting](#wait) for the client to reconnect, and if this not occur, unwinding all subscription state.
470−
471−
472−**Gifts given in response:** None.
473−
474−### 3.4 ``[%wart sock [path *]]``, inbound message
475−
476−Sometimes, messages are received from other ships. They are expected to take the from of a `gram`.
477−
478−**Gifts given in response:** [`%nice` or `%mean`](#ack).
479−
480−#### 3.4.1 `gram`
481−
482−There are three messages of note, all concerning authentication
483−- `[/lon ses]` is a login request, which contains the session wishing to authenticate.
484−- if the session is already authorized, a reply of `[/aut ses]` from (%eyre on) a foreign ship prescribes that the session is henceforth allowed to act on its behalf. All waiting `/~/as` are resolved as successful.
485−- otherwise, `[/hat ses hart]` contains the ship's preferred hostname. This can then be used to redirect the client. All waiting `/~/as` are given `307 Redirect`s to `/~/am` on the provided host.
486−
487−**Gifts given in response:** nice?
488−
489−## 4. Responses
490−
491−### 4.1 `[%nice ~]`, `[%mean ares]`, network acknowledgement
492−
493−A `%nice` is given upon receiving an [ames message](#gram), indicating succesful receipt. `%mean` is currently unused directly, but reserved for error conditions.
494−
495−## `[%sigh p=cage]`, inbound http response
496−
497−An HTTP response gets converted to the requested mark, or `%tang` in case of error.
498−
499−### 4.2 `[%thou httr]`, full HTTP response
500−
501−Most requests are served with one coherent response, consisting of
502−- `p=@ud`, an HTTP status code
503−- `q=mess`, response headers
504−- `r=(unit octs)`, an optional body
505−
506−### 4.3 `[%that httr]`, partial HTTP response
507−
508−[EventStream responses](#of-ixor) consist of multiple sequential chunks. Treated as `%thou`, except the request is kept open.
509−
510−### 4.4 `[%thar (unit octs)]`, partial HTTP body
511−
512−Complementing `%that`, `%thar` is a body chunk, containing an event. An empty `%thar` signals for the connection to be closed.
513−
514−Body chunks, besides `[1 '\0a']`(a heartbeat newline), are encoded from `even` events. The stem becomes the [`event` field](#eventsource), and the content, `data` lines.
515−
516−#### 4.4.1 `even`, event types
517−
518−There are three events that a [client subscription](#subs) will be given.
519−
520−- `[%news hash]` is a `%f` update, and contains the relevant dependency token.
521−- `[%mean [term path] ares]` is a sourced subscription error.
522−
523−## 5. Vane requests
524−
525−### 5.1 ``[%a %wont sock `[path *]`gram]``, outbound message
526−
527−The `%a` interface provides conveyance of [messages](#gram) over UDP.
528−
529−Signs a `%woot` upon message arrival.
530−
531−
532−All open [subscriptions](#of-ixor) require a "heartbeat" newline every `~s30`. When this fails to arrive, a complementary timer is set for `~m1`, after which the client is considered to have departed.
533−The `%b` timer interface is used to schedule the next such event, or cancel past scheduled ones when a connection closes.
534−
535−Signs a `%wake` upon timer activation.
536−
537−### 5.3 `[%f %wasp @uvI]`, dependency listen
538−
539−Knowledge of filesystem changes, requested by `/~/on` and `/~/in`, is requested the `%wasp` note. It contains the hash token which identifies a set of dependencies to query. Saved as a (live[live](#live)] request in case of cancellation when caused by `/~/on`.
540−
541−Signs a `%writ` upon change.
542−
543−### 5.4 `[%f %exec (unit silk)]`, functional transformations
544−
545−The `%f` interface converts [nouns](/docs/glossary/noun/) from one form to another. An empty unit represents cancellation.
546−
547−Signs a `%made` containing the computation result.
548−
549−The `silk`s used are as follows:
550−
551−### `[%cast %mime %boil mark beam [%web span ~]]`, file load
552−
553−The simplest functional request is the construction of a page. Saved as a [live](#live) request in case of cancellation.
554−- The `mark` is the request extension, defaulting to `%html`.
555−- A `beam`(path in `%clay`) is decoded from the request path.
556−- A `/web/<nyp ced quy>` virtual path is appended, span-encoding method, auth, and query string.
557−
558−### `[%cast mark %done ~ cage]`, convert
559−
560−This is used when communicating with apps, in both directions.
561−- Client messages are encoded as JSON objects, but can contain many different marks. Ones sent to non-`json.json` endpoints are `%cast` to he relevant mark, with a `cage` of `[%json p:!>(*json) jon]`, prior to being sent onwards to applications with `[%g %mess]`.
562−- Subscription responses also come in arbitrary marks, but are required to be sent as whichever mark an endpoint is subscribed to. They get `%cast` prior to being sent back as a `%that` EventSource segment.
563−
564−### 5.5 `%g`, app actions
565−
566−The end goal of many a userspace `hymn.hook` is to provide UI for a `%gall` app. To accommodate this, various functionality needs to be interfaced with.
567−
568−### `[%mess hapt ship cage]`, app message
569−
570−After a `/~/to` POST has been received, and possibly converted to the correct mark, it is sent to `%g` for processing. The `hapt` is the destination, the `ship` is the source, the `cage` is the marked message data.
571−
572−Signs a `%nice` or `%mean`, in userspace or upon crashing.
573−
574−### `[%show hapt ship path]`, app subscription
575−
576−An `/~/is` PUT, if not already registered, results in a new subscription. A request for such contains the destination `hapt`, requesting `ship`, and app-internal `path`.
577−
578−Signs a `%nice` on init, `%rush` on data, and a `%mean` in subscription termination.
579−
580−### `[%took hapt ship]`, %rush confirmation
581−
582−A `%took` must be sent to acknowledge the receipt of subscription data, which in this case occurs automatically.
583−
584−Causes no signs.
585−
586−### `[%nuke hapt $|(ship [ship path])]`, subscription cancel
587−
588−An `/~/is` DELETE is used to remove a subscription, and is converted straightforwardly to a `%nuke`. Additionally, when a client disconnects, all of its subscriptions are `%nuke`d to reflect their expiration.
589−
590−Signs an empty `%mean` for each open subscription that is closed.
591−
592−## 6. In-flight metadata
593−
594−Various state can be associated with requests, but not necessarily be returned in responses to them.
595−
596−### 6.1 `~`, dropthrough
597−
598−If the response should be sent statelessly further up the duct, the `wire` is empty. This is used in `%f` pure functional page generation.
599−
600−### 6.2 `[?(%y %n) ...]`, stability
601−
602−The first element of a [`%b` timer](#wait) path distinguishes between live(%y) and dying(%n) channels.
603−
604−### 6.3 `/of/[ixor]`, view
605−
606−Designates which stream to act upon. Present on `%b` timer cards.
607−
608−### 6.4 `/on/<deps>`
609−
610−Present on `%f` dependency news. Looked up in [the state](#bolo) to see if any response is necessary.
611−
612−### 6.5 `/to/<hasp>/<ship>`, app
613−
614−Present on `%f` translations of message marks
615−
616−### 6.6 `/is/[ixor]/{hasp path}`, subscription
617−
618−Subscription requests. Present on `%g` subscription requests, and `%f` translations of [`%rush` subscription data](#show).
619−
620−## 7. Vane responses
621−
622−The goal of requests is to cause some manner of result. Specifically,
623−
624−### 7.1 `[%a %woot ship coop]`, acknowledgement
625−
626−A [message](#mess) which has been acknowledged remotely.
627−
628−### 7.2 `[%b %wake ~]`, timer
629−
630−Timer activate. If this is a `%y` [timer](#wire-live), send a newline to each `/~/of/[oryx]`; if `%n` and the `oryx` still has no listeners, wipe its state/subscriptions.
631−
632−### 7.3 `[%f %news ~]`, dependency update
633−
634−This message signifies a `hash` has changed, and listeners to it should be updated. Results in [`%news` events](#even-news) to concerned streams, and [full responses](#thou) to relevant long-polls.
635−
636−### 7.4 `[%f %made (each bead (list tank))]`, compute result
637−
638−Further action depends on the [`wire`](#whir). It can:
639−- Be empty, designating direct request data, which is [served](#mime) back up the `duct`.
640−- Contain [app and requester identities](#wire-to), which designates an app message has been converted to the correct `mark`, and can now be [sent to the app](#mess) with an empty `wire`.
641−- Contain an `oryx`, app, and `path`, designating subscription data. If the subscription is active in the relevant `stem`, it is acknowledged with a `%took` and given as a [`%rush` event](#even-rush) to all listeners. Otherwise, the subscription is `%nuke`d.
642−
643−### 7.5 `%g`, applications
644−
645−The `%g` interface sends several responses.
646−
647−### `[%nice ~]` and `[%mean ares]`, acknowledgment
648−
649−These are given as a response to `%mess`, with an empty wire, and `%show`s, with a [subscription wire](#wire-is).
650−The former is [served](#mime) back to the requester(i.e. the remaining duct), and the latter returned to the client.
651−
652−#### 7.5 `[%rush cage]`, subscription data
653−
654−A `%rush` arrives on a [subscription wire](#wire-is), and is then sent [for conversion](#done) to the correct mark. An unexpected `%rush` is `%nuke`d.
655−
656−## 8. Server state
657−
658−There is a quantity of data that persists between events.
659−
660−### 8.1 Global
661−
662−- `path` the default path which is prepended to relative plain requests. Initialized to `/<our>`, the serving ship; this interprets the first element of requests as a desk, and injects a `case` of `0`.
663−- `(jar ship hart)` remembered hostnames in order of preference, made accessible through `.^`
664− + The default values(for self) are `http://<ship>.urbit.org:80` if not on a fake network, followed by `https://0.0.0.0:[port]`.
665−- `(jug deps (each duct oryx))`, `/~/on` and `/~/in` endpoints listening to `%c` updates.
666−- `(map duct live)`, inbound request state
667−- `(map ixor oryx)`, open `/~/of` streams.
668−- `(map oryx stem)`, open view state.
669−- `(map hole sink)`, session state.
670−- `(map hole ,[ship ?])`, foreign session names, along with their origin ships and whether they are authorized to act on our behalf.
671−
672−### 8.2 `live`, per-request state
673−
674−To honor request cancellations, each unserved request must track which effect it is causing.
675−+ `[%exec whir]` if it is a ford data request
676−+ `[%wasp (list @uvH)]` if it is a ford dependency poll
677−+ `[%xeno ship]` if this is a proxied request
678−+ `[%poll ixor]` if this is a session long-poll
679−
680−### 8.3 `sink`, per-session state
681−
682−Each `hole` has associated authentication state.
683−- `priv`, a random secret that verifies the session, stored in cookie.
684−- `[ship (set ship)]`, the `ship` a session is acting as and any others it has been authorized with.
685−- `(jug ship ,[path duct])`, authentication `/~/as` requests waiting on foreign ships.
686−- `(set oryx)`, views associated with this session. Dual of `hole` in `stem`.
687−
688−### 8.4 `stem`, per-view state
689−
690−Each `oryx` has active subscription state.
691−- `hole`, session in which this view resides. Dual of `(set oryx)` in `sink`.
692−- `ixor`, a cached hash of the `oryx` that is used as a subscription id, by the `/~/of` EventStream.
693−- `[,@u (map ,@u even)]`, queued [events](#even). Has a maximum size.
694−- `(unit ,[duct @u ?])`, http connection, its last received event, and whether it is a long-poll request.
695−- `(set deps)`, subscribed `/~/in` points. Mirrored in `bolo`.
696−- `(map ,[hasp path] mark)`, subscribed `/~/is` points
697−- `(que duct)`, where any `%nice`/`%mean
698−
699−## Appendix A: Glossary
700−
701−- An `oryx` is a CSRF token used for [authenticated requests](#auth)
702−- `mean.json` is a rendering of hoon `ares`: an error message formatted as `{fail:'type',mess:"Error message"}`
703−- `urb.js` is the standard client-side implementation of the `%eyre` protocols, normally found in `/=main=/lib`
704−- The act of "serving", refers to the wrapping of a `%mime` cage in an HTTP `200 Success` response, and errors or other marks being [sent to ford](#done) for conversion. Inside a `sign`, this conversion occurs along the same [`wire`](#wire); otherwise, the `wire` is [empty](#wire-drop).
705−
706−## Appendix B: EventSource
707−
708−UNIMPLEMENTED
709−
710−For more information, see <http://dev.w3.org/html5/eventsource/>
711−
712−An EventSource is a stream of events, encoded in a conceptually infinite `GET` request. Each event is formatted as
713−```
714− http
715− id: {number}
716− event: {type}
717− data: {contents}
718− data: {more-contents}
719−```
720−
721−Data lines are joined by ASCII `10` newline characters; multiple newlines signify separate events. The `id` is used in a `Last-Event-ID` HTTP request header upon reconnection.
61+- [Examples](@/docs/arvo/eyre/examples.md) - Practical examples of the different ways of using Eyre.
content/docs/arvo/eyre/scry.mdnew file+213
@@ -0,0 +1,213 @@
1++++
2+title = "Scry Reference"
3+weight = 4
4+template = "doc.html"
5++++
6+
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+
25+Here 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.
26+
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>=)`.
28+
29+All examples are run from the dojo.
30+
31+# `/cors`
32+
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.
34+
35+Example:
36+
37+```
38+> .^(cors-registry:eyre %ex /=//=/cors)
39+[ requests={~~http~3a.~2f.~2f.baz~.example}
40+ approved={~~http~3a.~2f.~2f.foo~.example}
41+ rejected={~~http~3a.~2f.~2f.bar~.example}
42+]
43+```
44+
45+## `/cors/requests`
46+
47+An `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)`.
48+
49+Example:
50+
51+```
52+> .^(requests=(set origin:eyre) %ex /=//=/cors/requests)
53+requests={~~http~3a.~2f.~2f.baz~.example}
54+```
55+
56+## `/cors/approved`
57+
58+An `x` scry with a `path` of `/cors/approved` will return the `set` of approved CORS origins. The type returned is a `(set origin:eyre)`.
59+
60+Example:
61+
62+```
63+> .^(approved=(set origin:eyre) %ex /=//=/cors/approved)
64+approved={~~http~3a.~2f.~2f.foo~.example}
65+```
66+
67+## `/cors/approved/<origin>`
68+
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 `?`.
70+
71+The 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'`.
72+
73+Examples:
74+
75+```
76+> .^(? %ex /=//=/cors/approved/(scot %t 'http://foo.example'))
77+%.y
78+```
79+
80+```
81+> .^(? %ex /=//=/cors/approved/(scot %t 'http://bar.example'))
82+%.n
83+```
84+
85+## `/cors/rejected`
86+
87+An `x` scry with a `path` of `/cors/rejected` will return the `set` of rejected CORS origins. The type returned is a `(set origin:eyre)`.
88+
89+Example:
90+
91+```
92+> .^(rejected=(set origin:eyre) %ex /=//=/cors/rejected)
93+rejected={~~http~3a.~2f.~2f.bar~.example}
94+```
95+
96+## `/cors/rejected/<origin>`
97+
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 `?`.
99+
100+The 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'`.
101+
102+Examples:
103+
104+```
105+> .^(? %ex /=//=/cors/rejected/(scot %t 'http://bar.example'))
106+%.y
107+```
108+
109+```
110+> .^(? %ex /=//=/cors/rejected/(scot %t 'http://foo.example'))
111+%.n
112+```
113+
114+# `/authenticated/cookie/<cookie>`
115+
116+An `x` scry whose `path` is `/authenticated/cookies/<cookie>` tests whether the given cookie is currently valid. The type returned is a `?`.
117+
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'`.
119+
120+Examples:
121+
122+```
123+> .^(? %ex /=//=/authenticated/cookie/(scot %t 'urbauth-~zod=0vvndn8.bfsjj.j3614.k40ha.8fomi'))
124+%.y
125+```
126+
127+```
128+> .^(? %ex /=//=/authenticated/cookie/(scot %t 'foo'))
129+%.n
130+```
131+
132+# `bindings`
133+
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).
135+
136+Example:
137+
138+```
139+> .^((list [binding:eyre duct action:eyre]) %e /=bindings=)
140+~[
141+ [ [site=~ path=<|~landscape js bundle|>]
142+ ~[/gall/use/file-server/0w2.EijQB/~zod/~landscape/js/bundle /dill //term/1]
143+ [%app app=%file-server]
144+ ]
145+ [ [site=~ path=<|~landscape|>]
146+ ~[/gall/use/file-server/0w2.EijQB/~zod/~landscape /dill //term/1]
147+ [%app app=%file-server]
148+ ]
149+ ...(truncated for brevity)...
150+]
151+```
152+
153+# `connections`
154+
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).
156+
157+Example:
158+
159+```
160+> .^((map duct outstanding-connection:eyre) %e /=connections=)
161+{}
162+```
163+
164+# `authentication-state`
165+
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.
167+
168+Example:
169+
170+```
171+> .^(authentication-state:eyre %e /=authentication-state=)
172+ sessions
173+{ [ p=0v3.kags1.hj7hm.6llrl.cga2j.eh1r7
174+ q=[expiry-time=~2021.5.20..08.44.27..39e0 channels={}]
175+ ]
176+}
177+```
178+
179+# `channel-state`
180+
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).
182+
183+Example:
184+
185+```
186+> .^(channel-state:eyre %e /=channel-state=)
187+[ session
188+ { [ p='1601844290-ae45b'
189+ q
190+ [ state=[%.y p=[date=~2021.5.13..20.44.27..39e0 duct=~[//http-server/0v2.kmj6q/26/1]]]
191+ next-id=1
192+ last-ack=~2021.5.13..08.44.27..39e0
193+ events={[id=0 request-id=2 channel-event=[%poke-ack p=~]]}
194+ unacked={}
195+ subscriptions={}
196+ heartbeat=~
197+ ]
198+ ]
199+ }
200+ duct-to-key={}
201+]
202+```
203+
204+# `host`
205+
206+A 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`.
207+
208+Example:
209+
210+```
211+> .^(hart:eyre %e /=host=)
212+[p=%.n q=[~ 8.080] r=[%.y p=<|localhost|>]]
213+```
content/docs/arvo/eyre/tasks.mdnew file+230
@@ -0,0 +1,230 @@
1++++
2+title = "Internal API Reference"
3+weight = 3
4+template = "doc.html"
5++++
6+
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+
24+This 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.
25+
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.
27+
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.
29+
30+# `%live`
31+
32+```hoon
33+[%live insecure=@ud secure=(unit @ud)]
34+```
35+
36+This `task` notifies Eyre of the listening HTTPS and HTTP ports. It is automatically sent to Eyre by the runtime and should not be used manually.
37+
38+The `insecure` field is the HTTP port and `secure` is the optional HTTPS port.
39+
40+## Returns
41+
42+Eyre returns no `gift` in response to a `%live` `task`.
43+
44+# `%rule`
45+
46+```hoon
47+[%rule =http-rule]
48+```
49+
50+This `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.
51+
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.
53+
54+## Returns
55+
56+Eyre returns no `gift` in response to a `%rule` `task`.
57+
58+# `%request`
59+
60+```hoon
61+[%request secure=? =address =request:http]
62+```
63+
64+This `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.
65+
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.
67+
68+## Returns
69+
70+Eyre may `pass` a `%response` `gift` on the appropriate `duct` depending on the contents of the `%request`, state of the connection, and other factors.
71+
72+# `%request-local`
73+
74+```hoon
75+[%request-local secure=? =address =request:http]
76+```
77+
78+This `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.
79+
80+## Returns
81+
82+Eyre may `pass` a `%response` `gift` on the appropriate `duct` depending on the contents of the `%request`, state of the connection, and other factors.
83+
84+# `%cancel-request`
85+
86+```hoon
87+[%cancel-request ~]
88+```
89+
90+This `task` is sent to Eyre by the runtime when an HTTP client closes its previously established connection. You would not normally use this manually.
91+
92+This `task` takes no arguments.
93+
94+## Returns
95+
96+Eyre may `pass` a `%response` `gift` on the appropriate `duct` depending on the state of the connection and other factors.
97+
98+# `%connect`
99+
100+```hoon
101+[%connect =binding app=term]
102+```
103+
104+This `task` binds a Gall agent to a URL path so it can receive HTTP requests and return HTTP responses directly.
105+
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.
107+
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.
109+
110+Along 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).
111+
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.
113+
114+The `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.
115+
116+Finally, 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.
117+
118+## Returns
119+
120+Eyre will respond with a `%bound` `gift` which says whether the binding was successful and looks like:
121+
122+```hoon
123+[%bound accepted=? =binding]
124+```
125+
126+The `accepted` field says whether the binding succeeded and the `binding` is the requested binding described above.
127+
128+## Example
129+
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.
131+
132+# `%serve`
133+
134+```hoon
135+[%serve =binding =generator]
136+```
137+
138+This `task` binds a generator to a URL path so it can receive HTTP requests and return HTTP responses.
139+
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 `~`.
141+
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).
143+
144+The sample of the first gate must be:
145+
146+```hoon
147+[[now=@da eny=@uvJ bec=beak] ~ ~]
148+```
149+
150+...and the sample of the second, nested gate must be:
151+
152+```hoon
153+[authenticated=? =request:http]
154+```
155+
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.
157+
158+The `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.
159+
160+## Returns
161+
162+Eyre will return a `%bound` `gift` as described at the end of the [%connect](#connect) section.
163+
164+## Example
165+
166+See the [Generators](@/docs/arvo/eyre/examples.md#generators) section of the [Examples](@/docs/arvo/eyre/examples.md) document for an example.
167+
168+# `%disconnect`
169+
170+```hoon
171+[%disconnect =binding]
172+```
173+
174+This `task` deletes a URL binding previously set by a `%connect` or `%serve` `task`.
175+
176+The [binding](@/docs/arvo/eyre/data-types.md#binding) is the URL path and domain of the binding you want to delete.
177+
178+## Returns
179+
180+Eyre returns no `gift` in response to a `%disconnect` `task`.
181+
182+# `%code-changed`
183+
184+```hoon
185+[%code-changed ~]
186+```
187+
188+This `task` tells Eyre that the web login code has changed, causing Eyre to throw away all sessions and cookies. Typically it's automatically sent to Eyre by `hood` when you run `|code %reset`.
189+
190+This `task` takes no arguments.
191+
192+## Returns
193+
194+Eyre returns no `gift` in response to a `%code-changed` `task`.
195+
196+# `%approve-origin`
197+
198+```hoon
199+[%approve-origin =origin]
200+```
201+
202+This `task` tells Eyre to start responding positively to CORS requests for the specified `origin`.
203+
204+The [origin](@/docs/arvo/eyre/data-types.md#origin) is a CORS origin like `http://foo.example` you want to approve.
205+
206+## Returns
207+
208+Eyre returns no `gift` in response to a `%approve-origin` `task`.
209+
210+## Example
211+
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.
213+
214+# `%reject-origin`
215+
216+```hoon
217+[%reject-origin =origin]
218+```
219+
220+This `task` tells Eyre to start responding negatively to CORS requests for the specified `origin`.
221+
222+The [origin](@/docs/arvo/eyre/data-types.md#origin) is a CORS origin like `http://foo.example` you want want to reject.
223+
224+## Returns
225+
226+Eyre returns no `gift` in response to a `%reject-origin` `task`.
227+
228+## Example
229+
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.
content/docs/arvo/eyre/using-eyre.mddeleted−230
@@ -1,230 +0,0 @@
1−+++
2−title = "Using Eyre"
3−description = "How to work with eyre from outside Urbit."
4−weight = 20
5−template = "doc.html"
6−+++
7−
8−This guide is aimed at developers who have a working knowledge of HTTP grammar (`PUT`, `GET`), and should not require any special knowledge of Urbit's internals. To learn more about a specific application within Urbit, please search for that with the docs once you have finished this guide.
9−
10−## Prerequisites
11−
12−You'll need a working development ship to follow along with this guide. It's
13−recommended that you set up a new "fakezod" on port 8080: Run this code,
14−substituting the appropriate path to your Urbit binary:
15−
16−```bash
17−/path/to/urbit -p 8080 -F zod
18−```
19−
20−For the unfamiliar, this will create a folder named "zod" in your working directory, from which the ship will run. Use `/path/to/urbit -p 8080 zod` in the future. For more information on this process, see our guide on [Environment Setup](/docs/development/environment).
21−
22−## Authentication
23−
24−We'll authenticate with a code that can be retrieved from the dojo. You can run
25−`+code` in the dojo to obtain it, but a fakezod's code is always
26−`lidlut-tabwed-pillex-ridrup`.
27−
28−Run this code in your bash terminal (requires cURL):
29−
30−```bash
31−curl -i localhost:8080/~/login -X POST -d "password=lidlut-tabwed-pillex-ridrup"
32−```
33−Let's explain what this does:
34−
35− - `-i` displays the headers, so that you can see the cookie that gets sent
36− - `localhost:8080/~/login` is the URL to which you are POSTing. You will note this is also the URL you visit when you log into Landscape.
37− - `-X POST` specifies that you are POSTing data, not GETting.
38− - `-d "password=lidlut-tabwed-pillex-ridrup"` specifies the code for your Urbit that we retrieved above. It is sent as form data, as if it were sent from an HTML form input field (which it is in Landscape)
39−
40−You should see the following:
41−
42−```bash
43−HTTP/1.1 200 ok
44−Date: Sun, 01 Jan 2020 00:00:00 GMT
45−Connection: keep-alive
46−Server: urbit/vere-0.10.8
47−set-cookie: urbauth-~zod=0v3.fvaqc.nnjda.vude1.vb5l6.kmjmg; Path=/; Max-Age=604800
48−transfer-encoding: chunked
49−```
50−
51−The `Date` and `set-cookie` will be slightly different of course.
52−
53−Take a look at the `set-cookie` line. This is now your session authentication, and will need to be sent with any future requests. It consists of three parts:
54−
55− - `urbauth` is a prefix that Eyre uses to check for presence of authentication
56− - `~zod` is the name of the ship you are logging in as
57− - `0v3.fvaqc.nnjda.vude1.vb5l6.kmjmg` is the actual authentication token.
58−
59−At present there is no way to separate these parts — you must pass a cookie *as* a cookie. This string must be in the `Cookie` header. The `set-cookie` header is only used for this request upon response. It is what browsers expect when receiving a cookie.
60−
61−## Interacting with Eyre
62−
63−Once authenticated, you will perform all your operations on a channel. You may open as many channels as needed using the same authentication token, but this will increase complexity and memory usage on your Urbit ship.
64−
65−Interacting with Urbit comprises two parts:
66−
67−1. Sending information via PUT requests, which receive HTTP status code `204` (no content) upon success. We will not receive updated information (as in a POST request).
68−2. Receiving data on channels, which must first be subscribed to via an initial request. These come in the form of SSEs ([Server-Sent Events](https://www.w3.org/TR/eventsource/))
69−
70−These can be used independently, i.e. you may choose to only send information or only receive information from your Urbit, based on your application. Both can take place on the same channel.
71−
72−### Creating a Channel
73−
74−For this example, we will use the following channel:
75−
76−```
77−http://localhost:8080/~/channel/1601844290-ae45b
78−```
79−
80−Let's examine the parts. A channel is simply a URL in this pattern: `{url}/~/channel/{uid}` where `{uid}` is a string of your choosing. Most libraries default to the current unix time plus six hexadecimal characters. Your program should determine a channel for its current session and store that in its state.
81−
82−The channel does not yet exist in Urbit, however. To subscribe to events on this URL, you must first make a request (PUT) to Urbit on this URL. The simplest way to do this is to `hi` ourselves, as if we had entered `|hi our` in the dojo. A `hi` is analogous to a ping, and does not manipulate state. Let's learn how to make requests using this as an example.
83−
84−### Making Requests
85−
86−All requests will take the form of sending a message. Messages can take different forms, such as `subscribe`s, `ack`s, and `poke`s. These are called actions and there are more than these, but these will cover most basic use cases. You can think of them as a somewhat more sophisticated HTTP grammar. A message always requires an `id` and an `action`. Other fields depend on the specific action.
87−
88−Let's look at the structure of a message by examining the most basic `hi` we will send.
89−
90−```js
91−{
92− 'id': 1, // Required. A sequential ID. Keep track of which messages you have sent.
93− 'action': 'poke', // Required. The action to take. poke is the most basic way of sending data, like HTTP POST
94− 'ship': 'zod', // Required by poke. The ship on which to perform the poke. You can only poke foreign ships with JSON, but this is the authenticated ship.
95− 'app': 'hood', // Required by poke. The Urbit app to which to send the data.
96− 'mark': 'helm-hi', // Required by poke. The "mark," or type, of data being sent.
97− 'json': 'Opening airlock' // Required by poke. The actual data being sent.
98−}
99−```
100−
101−Let's open our channel by sending the following request using cURL (**remember to change the cookie**):
102−
103−```bash
104−curl --header "Content-Type: application/json" \
105− --cookie "urbauth-~zod=0v3.fvaqc.nnjda.vude1.vb5l6.kmjmg" \
106− --request PUT \
107− --data '[{"id":1,"action":"poke","ship":"zod","app":"hood","mark":"helm-hi","json":"Opening airlock"}]' \
108− http://localhost:8080/~/channel/1601844290-ae45b
109−```
110−
111−If you switch to your fakezod's dojo, you should see `< ~zod: Opening airlock`.
112−
113−Note that in the JSON that we sent via `--data`, the payload is wrapped in `[]`. This is because we can send multiple messages in a single payload, and Eyre expects a list of items, even if we are only sending one.
114−
115−You will always receive a `204` status code if the `PUT` request successfully reached Urbit, authentication succeeded, and the payload was valid. This is merely an HTTP status code, however. If the request failed within Urbit itself, however, you will receive a "nack" event that you will have to process separately.
116−
117−Let's look at how to receive events from Urbit.
118−
119−### Subscribing to Events
120−
121−Now that Urbit has opened an Eyre channel at our URL, we can watch for events on that URL by sending a `subscribe` message. Let's look at the anatomy of a `susbcribe`:
122−
123−```js
124−{
125− 'id': 2, // Required. This is the next message we are sending, so we give it the next ID.
126− 'action': 'subscribe', // Required.
127− 'ship': 'zod', // Required by subscribe.
128− 'app': 'chat-view', // Required by subscribe. In this case, we want to watch events that occur in the chat-view app, which is responsible for handling incoming chats.
129− 'path': '/primary' // Required by subscribe. All apps have different path structures. In the case of chat-view, this is where we see all incoming chats.
130−}
131−```
132−
133−This is all we need to send Urbit to say "On this URL through which I am sending information, send me SSEs whenever something occurs on this app at this path."
134−
135−You should be able to send this information if you were able to send the above cURL example. However, we now need to be able to listen to the SSEs. The `EventSource` object is available for JavaScript in the browser context, as this is why SSEs were invented, but there should be a library for it in your chosen language. Take a look at a Browser JavaScript example:
136−
137−```js
138−const eventSource = new EventSource('http://localhost:8080/~/channel/1601844290-ae45b', {
139− withCredentials: true // Required, sends your cookie
140−});
141−
142−eventSource.addEventListener('message', function (event) {
143− ack(Number(event.lastEventId)); // See section below
144− const payload = JSON.parse(event.data); // Data is sent in JSON format
145− payload.id === event.lastEventId; // The SSE spec includes event IDs. This information is duplicated in the payload.
146− const data = payload.json; // Beyond this, the actual data will vary between apps
147−});
148−
149−eventSource.addEventListener('error', function (event) {
150− handleError(event);
151−});
152−
153−```
154−
155−### Handling Received Events
156−
157−Once you have received an event, it is expected that you will "ack" or "acknowledge" that you have received them. To do so, simply send a message in the following format:
158−
159−```js
160−{
161− 'id': 3, // Required. Picking up where we left off
162− 'action': 'ack', // Required.
163− 'event-id': 15, // Required by ack. Whichever SSE of which you are acknowledging receipt
164−}
165−```
166−
167−### Unsubscribing from Events
168−
169−You may want to stop receiving events from a particular app path, but you don't want to close the channel altogether yet. Let's look at how to do that. Take a look at the example for subscribing. We sent that message with `id: 2`. We will use that ID to cancel the relevant subscription:
170−
171−```javascript
172−{
173− 'id': 4, // Required. We always increment the ID as we send messages.
174− 'action': 'unsubscribe', // Required.
175− 'subscription': 2 // Required by unsubscribe. This corresponds to the id of a subscribe message sent earlier.
176−}
177−```
178−
179−### Deleting a Channel
180−
181−You should clean up your channel when able. To do so, simply send a `delete` message and Eyre will handle the rest so your program can safely exit.
182−
183−```javascript
184−{
185− 'id': 5, // Required.
186− 'action': 'delete' // Required.
187−}
188−```
189−
190−## Other Operations
191−
192−There are other operations which require authentication but do not require the use of a channel. Some operations are app-specific and will not be enumerated here, but there are two operations that exist across Urbit: `scry` and `spider`.
193−
194−### Scrying
195−
196−Scrying lets you see what an app has exposed at a particular path. It does not manipulate state.
197−
198−It takes the form `{url}/~/scry/{app}{path}.{mark}`
199−
200− Let's get the base hash of our fakezod in the same way that Landscape does it.
201−
202−```bash
203−curl --header "Content-Type: application/json" \
204− --cookie "urbauth-~zod=0v3.fvaqc.nnjda.vude1.vb5l6.kmjmg" \
205− --request GET \
206− http://localhost:8080/~/scry/file-server/clay/base/hash.json
207−```
208−
209−Note the use of a `GET` request.
210−
211−In this example we're scrying the `file-server` app at the path `/clay/base/hash` and using the `json` mark, which is most common. We receive `"0"` which is correct because we are at the top level of the hierarchy using a fake ship.
212−
213−Scry will fail with a 500 or return a 404 if no data is found.
214−
215−### Running Threads with Spider
216−
217−Running threads is an exception to the rule that we outlined in the section on channels. It uses a `POST` request and both manipulates state and receives information back. It also exposes the ability to send a sequence of commands, i.e. a "thread," hence the name.
218−
219−It takes the form `{url}/spider/{inputMark}/{threadname}/{outputmark}.json`
220−
221−This should be considered an advanced technique, but the basic structure of a request can be seen here:
222−
223−```bash
224−curl --header "Content-Type: application/json" \
225− --cookie "urbauth-~zod=0v3.fvaqc.nnjda.vude1.vb5l6.kmjmg" \
226− --request POST \
227− --data '[{"foo": "bar"}]' \
228− http://localhost:8080/spider/graph-view-action/graph-create/json.json
229−
230−```
content/docs/arvo/reference/_index.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "Reference"
3+weight = 1
4+sort_by = "weight"
5+template = "sections/docs/chapters.html"
6++++
7+
8+[Cryptography](@/docs/arvo/reference/cryptography.md)
9+
10+An overview of where Arvo uses cryptography, what algorithms are used, and how
11+they are implemented.
content/docs/arvo/reference/cryptography.mdnew file+222
@@ -0,0 +1,222 @@
1++++
2+title = "Cryptography"
3+weight = 10
4+template = "doc.html"
5++++
6+
7+This is a summary of the cryptography functions found in `sys/zuse.hoon`, Arvo's
8+standard library. This page currently only documents cryptographic functions
9+directly utilized by [Ames](@/docs/arvo/ames/ames.md). `zuse` also contains
10+cryptographic functions relevant to Ethereum such as the `+keccak:crypto` core,
11+but they are currently undocumented.
12+
13+Documentation for [Insecure Hashing](@/docs/hoon/reference/stdlib/2e.md) and the
14+[SHA Hash Family](@/docs/hoon/reference/stdlib/3d.md) is found in the Hoon standard
15+library reference.
16+
17+## Summary
18+
19+`zuse` contains several cryptosuites. The ones utilized by Ames are
20+[`+ed:crypto`](#ed), [`+aes:crypto`](#aes), and [`+crub:crypto`](#crub), with
21+the latter being the only one which is implemented as an [`+acru:ames`](@/docs/arvo/ames/cryptography.md#crypto-core)-shaped core.
22+
23+## `+crub:crypto` {#crub}
24+
25+`+crub:crypto` implements an
26+[`+acru:ames`](@/docs/arvo/ames/cryptography.md#crypto-core) core that implements
27+[Suite B Cryptography](https://en.wikipedia.org/wiki/NSA_Suite_B_Cryptography).
28+
29+It utilizes AES symmetric key encryption and decryption from [`+aes:crypto`](#aes)
30+implemented using the Diffie-Hellman key exchange protocol, elliptic curve
31+digital signature algorithm (ECDSA) signing and verification with [`+ed:crypto`](#ed),
32+and generates public/private key pairs using elliptic curve cryptography with
33+`+ed:crypto`.
34+
35+A `+crub:crypto` core's payload contains public encryption and authentication
36+keys and optional secret encryption and authentication keys.
37+
38+```hoon
39+ ++ crub !:
40+ ^- acru
41+ =| [pub=[cry=@ sgn=@] sek=(unit [cry=@ sgn=@])]
42+ |%
43+ ...
44+```
45+
46+`+crub` cores (because they follow the `+acru` interface) are typically created using one of the constructors in [`+nu:crub`](#nu).
47+
48+### `+seal:as`
49+
50+```hoon
51+ ++ seal ::
52+ |= [bpk=pass msg=@]
53+ ...
54+```
55+
56+Forms a symmetric key using Diffie-Hellman key exchange with the secret key
57+stored at `sgn.u.sek` and a public key `bpk`. Then `+sign`s `msg`, encrypts the
58+signed message using `+en:siva:aes` with the symmetric key, and then `+jam`s it.
59+
60+Crashes if `sek` is null.
61+
62+### `+sign:as` {#sign-as}
63+
64+```hoon
65+ ++ sign ::
66+ |= msg=@
67+ ...
68+```
69+
70+Signs message `msg=@` using the secret authentication key `sgn.u.sek`, then forms a
71+cell `[signed-message msg]` and `+jam`s it.
72+
73+Crashes if `sek` is null.
74+
75+### `+sure:as`
76+
77+```hoon
78+ ++ sure ::
79+ |= txt=@
80+ ...
81+```
82+
83+`+cue`s `txt` to get a signature `sig=@` and message `msg=@`. Verifies that
84+`sig` was `msg` signed using the secret key associated to the public key stored
85+at `sgn.pub`. Returns `(unit msg)` if so, null otherwise.
86+
87+### `+tear:as`
88+
89+```hoon
90+ ++ tear ::
91+ |= [bpk=pass txt=@]
92+ ...
93+```
94+
95+Forms a secret symmetric key using Diffie-Hellman key exchange using the secret
96+key `cry.u.sek` and encryption key part of the public key `bpk` (which here is a
97+concatenation of both the encryption and authentication public keys). `+cue`s
98+`txt` and decrypts it using `+de:siva:aes` with the symmetric key. If decryption
99+is successful, verifies the decrypted message using authentication key part of
100+`bpk`, and returns it if so. Returns null otherwise.
101+
102+Crashes if `sek` is null.
103+
104+### `+de`
105+
106+```hoon
107+ ++ de :: decrypt
108+ |= [key=@J txt=@]
109+ ...
110+```
111+
112+`+cue`s `txt` then decrypts with the symmetric key `key` using `+de:sivc:aes`.
113+Returns null in case of failure.
114+
115+### `+dy`
116+
117+```hoon
118+ ++ dy :: need decrypt
119+ |= [key=@J cph=@]
120+ ...
121+```
122+
123+Same as `+dy`, but crashes in case of failure.
124+
125+### `+en` {#en}
126+
127+```hoon
128+ ++ en :: encrypt
129+ |= [key=@J msg=@]
130+```
131+
132+Encrypts `msg` with the symmetric key `key` using `en:sivc:aes`, then `+jam`s
133+it.
134+
135+### `+fig:ex`
136+
137+Returns the fingerprint (SHA-256) of `+pub:ex`.
138+
139+### `+pac:ex`
140+
141+Returns the fingerprint (SHA-256) of `+sec:ex`. Crashes if `sek` is null.
142+
143+### `+pub:ex`
144+
145+Returns the concatenation of `sgn.pub` and `cry.pub`.
146+
147+### `+sec:ex`
148+
149+Returns the concatenation of `sgn.u.sek` and `cry.u.sek`.
150+
151+### `+pit:nu` {#nu}
152+
153+```hoon
154+ ++ pit :: create keypair
155+ |= [w=@ seed=@]
156+ ...
157+```
158+
159+Creates a `+crub` core with encryption and authentication public/private keypairs
160+generated from a bitwidth `w` and `seed`. The private keys are generated with
161+SHA-512, while `+puck:ed:crypto` is used to derive the public keys from the
162+private keys.
163+
164+This is how one typically generates a brand new `+crub` core for signing and
165+encrypting your own messages.
166+
167+### `+nol:nu`
168+
169+```hoon
170+ ++ nol :: activate secret
171+ |= a=ring
172+ ...
173+```
174+
175+Takes in a `ring` from a `+sec:ex:crub` and generates a new `+crub` core with
176+`sek` taken from `+sec:ex` and `pub` generated with `+puck:ed:crypto`. Crashes
177+if `+sec:ex` is not a `+crub` secret key.
178+
179+### `+com:nu`
180+
181+```hoon
182+ ++ com :: activate public
183+ |= a=pass
184+ ...
185+```
186+
187+Takes in a `pass` from a `+pub:ex:crub` and generates a new `+crub` core with
188+`pub` taken from `+pub:ex` and null `sek`.
189+
190+## `+ed:crypto` {#ed}
191+
192+This core contains cryptographic primitives and helper functions for elliptic
193+curve cryptography with [Curve25519](https://en.wikipedia.org/wiki/Curve25519).
194+
195+`+ed:crypto` is primarily used to generate public/private keypairs from a seed
196+for use with [elliptic curve
197+Diffie-Hellman](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman)
198+key agreements as well as [Elliptic Curve Digital Signature
199+Algorithm](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm).
200+These functionalities are ultimately utilized by [`+crub:crypto`](#crub), the
201+only cryptosuite which [Ames](@/docs/arvo/ames/ames.md) makes use of.
202+
203+Most gates in `+ed:crypto` are [jetted](@/docs/vere/jetting.md), meaning that an
204+external reference library is utilized whenever these functions are called,
205+rather than running in Nock natively. See the [Vere
206+documentation](@/docs/vere/cryptography.md#ed) for more information about the
207+library utilized by jets.
208+
209+## `+aes:crypto` {#aes}
210+
211+This core contains cryptographic primitives and helper functions for
212+[AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) symmetric key
213+encryption and decryption. As is the case with `ed:crypto`, these
214+functionalities are utilized by [`+crub:crypto`](#crub), and most gates are
215+jetted. See also the Vere documentation on [AES
216+SIV](@/docs/vere/cryptography.md#aes) for more information about the library
217+utilized by jets.
218+
219+This core contains several doors, each one used for a different variation of AES
220+according to key size and mode. The only ones currently in use are
221+`+siva:aes:crypto` and `+sivc:aes:crypto`, which are 128-bit and
222+256-bit modes of [`AES-SIV`](https://www.aes-siv.com) respectively.
content/docs/arvo/reference/filesystem.mdnew file+69
@@ -0,0 +1,69 @@
1++++
2+title = "Filesystem Hierarchy"
3+weight = 20
4+template = "doc.html"
5++++
6+
7+Here we describe what each of the primary folders present in the `%home` `desk`
8+are used for. This organization is merely a convention, and the exact location
9+of any file does not affect its operation. That being said, some [Ford
10+runes](@/docs/arvo/ford/ford.md) are designed with this structure in mind, and
11+applications such as dojo look in specific folders for code to run. Furthermore,
12+this organization is not perfectly adhered to - sometimes you may find structure
13+definitions in `/lib`, for example.
14+
15+- `/app` contains userspace applications, i.e. [Gall
16+ agents](@/docs/userspace/gall/gall.md).
17+- `/gen` contains generators. Many applications make use of generators, but
18+ also each generator in this folder may be run from dojo using `+`. For
19+ example, `/gen/foo/hoon` is run with `+foo`.
20+- `/lib` contains libraries that may be shared by multiple agents, threads,
21+ generators, etc. However, this is not the location of the standard libraries
22+ (see `/sys`). Libraries are imported from `/lib` with `/+`.
23+- `/mar` contains [mark](@/docs/arvo/clay/architecture.md#marks) definitions.
24+- `/sur` contains shared [structure](@/docs/hoon/reference/rune/_index.md) definitions.
25+ Whenever you expect structures to be used by code across multiple files, it
26+ is recommended to place their shared structures in `/sur`. Structures are
27+ imported from `/sur` with `/-`.
28+- `/sys` contains the code that defines the kernel and standard libraries.
29+ `/sys/vane` contains the code for the vanes, aka kernel modules. `/sys` is
30+ the exception to the rule - structures and functions that are central to
31+ Hoon, Arvo, and its vanes, are all located within this folder rather than in
32+ `/lib` and `/sur`. See [below](#sys) for more information on `/sys`.
33+- `/ted` contains [threads](@/docs/userspace/threads/overview.md). These may be
34+ run from dojo using `-`. For example, `/ted/foo/hoon` is run with `-foo`.
35+- `/tests` contains unit tests intended to be run using the `test` thread. To
36+ run a particular test `+test-bar` in `/tests/foo.hoon` in dojo, enter `-test %/tests/foo/test-bar ~`. If a file is specified, every test in that file will
37+ run. If a folder is specified, every test in that folder will run.
38+
39+## `/sys` {#sys}
40+
41+`/sys` contains four files: `hoon.hoon`, `arvo.hoon`, `lull.hoon`, and
42+`zuse.hoon`. These are the files used to construct kernelspace. The chain of
43+dependencies is `hoon.hoon` -> `arvo.hoon` -> `lull.hoon` -> `zuse.hoon`. We
44+give a brief description of each of them.
45+
46+- `hoon.hoon` contains the Hoon compiler and the [Hoon standard
47+ library](@/docs/hoon/reference/stdlib/table-of-contents.md). The Hoon
48+ compiler is self-hosted. This is the first file loaded by the Nock virtual
49+ machine, [Vere](@/docs/vere/runtime.md), in order for it to learn how to
50+ interpret Hoon. The kelvin version number is the subject of `hoon.hoon`,
51+ currently at 140. One may see this from dojo by inspecting the subject with
52+ `.` and noting that `%140` is the final entry of the subject.
53+- `arvo.hoon` contains the [Arvo kernel](@/docs/arvo/overview.md) and
54+ additional structures and functions directly relevant to the kernel. This is
55+ Urbit's "traffic cop", and as such contains the structure definitions for
56+ call stacks such as `duct`s and `bone`s. Once Vere understands Hoon, it loads
57+ and interprets `arvo.hoon` to create the kernel. `hoon.hoon` is the subject
58+ of `arvo.hoon`.
59+- `lull.hoon` primarily contains structures shared among the kernel and its
60+ vanes, as well as a few functions. In particular, this includes the
61+ definitions of the `card`s utilized by each vane, each of which are
62+ documented in their respective documentation. `lull.hoon` is loaded by the
63+ kernel during the [larval stage](@/docs/arvo/overview.md#larval-stage-core)
64+ in order to prepare to create the vanes. `arvo.hoon` is the subject of `lull.hoon`.
65+- `zuse.hoon` is the Arvo standard library. It consists primarily of functions
66+ shared by the kernel and vanes, such as the ones related to
67+ [cryptography](@/docs/arvo/reference/cryptography.md). `zuse.hoon` is loaded
68+ by the larval kernel following `lull.hoon`. `lull.hoon` is the subject of
69+ `zuse.hoon`. Then `zuse` is the subject of the vanes.
content/docs/azimuth/azimuth.md+7−8
@@ -4,6 +4,7 @@ weight = 2
44template = "doc.html"
55aliases = ["/docs/learn/azimuth"]
66+++
7+
78Azimuth is a general-purpose public-key infrastructure (PKI) on the Ethereum blockchain, used as a platform for _Urbit identities_. You need such an identity to use the Arvo network.
89
910The primary way to interact with Azimuth is through our [Bridge](https://github.com/urbit/bridge) application and the node libraries that it depends on, [azimuth-js](https://github.com/urbit/azimuth-js) and [urbit-key-generation](https://github.com/urbit/urbit-key-generation). Take a look at the source and play around, or see [Getting Started](/getting-started/).
@@ -42,7 +43,7 @@ Think of your master ticket like a very high-value password. The master ticket i
4243
4344### Ownership Address
4445
45−An ownership address has all rights over the assets deeded to it. These rights are on-chain actions described and implemented in the Ecliptic, Azimuth's suite of governing smart-contracts.
46+An ownership address has all rights over the assets deeded to it. These rights are on-chain actions described and implemented in [Ecliptic](@/docs/glossary/ecliptic.md), Azimuth's suite of governing smart-contracts.
4647
4748### Proxies
4849
@@ -55,8 +56,8 @@ Proxy addresses allow you to execute non-ownership related actions like spawning
5556
5657- **Voting Proxy**
5758
58− Galaxies only. Galaxies are the part of the galactic senate, and this means
59− they can cast votes on new proposals including changes to the Ecliptic.
59+ Galaxies only. Galaxies are the part of the [Galactic Senate](@/docs/glossary/senate.md), and this means
60+ they can cast votes on new proposals including changes to Ecliptic.
6061
6162- **Spawn Proxy**
6263
@@ -72,7 +73,7 @@ series of algorithms that ultimately generate your keys and the Ethereum address
7273![](https://media.urbit.org/fora/proposals/UP-8.jpg)
7374
7475First, your `@q` is converted into a numeric value `E` as an intermediary step
75−by adding [salt](https://en.wikipedia.org/wiki/Salt_(cryptography)). Then by
76+by adding [salt](<https://en.wikipedia.org/wiki/Salt_(cryptography)>). Then by
7677adding additional salts, `E` is converted into a set of BIP39 seed phrases -
7778these are 24 word mnemonic sequences used to generate Ethereum wallets. You end up
7879with one seed phrase for each proxy associated with your ship, and these seed
@@ -88,15 +89,13 @@ generated.
8889Most Ethereum tokens use the ERC-20 standard for smart contracts. Urbit identities
8990are, however, essentially different from most Ethereum tokens, due to identities not
9091being fungible. Since any two stars will handle social-networking realities in a
91−different way, they will carry a different reputation. identities are to houses as
92−tokens are to gold.
92+different way, they will carry a different reputation.
9393
9494The ERC-721 standard, having been made specifically to provide a smart-contract
9595interface for non-fungible assets, serves our needs well. This is the standard
9696that we use for deeding Urbit identities.
9797
98−Identities, and all of their blockchain operations, are governed by the Ecliptic.
99−The Ecliptic is an Ethereum smart-contract that governs identity state and the
98+Identities, and all of their blockchain operations, are governed by Ecliptic. Ecliptic is an Ethereum smart-contract that governs identity state and the
10099ownership, spawn, management, and voting rights affiliated with your identities.
101100
102101For the technical implementation details, take a look at Azimuth's
content/docs/development/develop.md+2−2
@@ -12,7 +12,7 @@ contribute to. At a high level, you can:
1212
1313- [Build clients](#clients), which use Urbit as their back-end to store data and
1414 interact with the network
15−- [Develop agents](#agents), or more precisely [*gall*
15+- [Develop agents](#agents), or more precisely [_gall_
1616 agents](/docs/userspace/gall/gall), which are written in [Hoon](/docs/hoon/)
1717 and can best be thought of as microservices
1818- [Contribute to Urbit's core](#core), which involves contributing to Urbit
@@ -49,7 +49,7 @@ To get started quickly with the language of your choice, see the list
4949libraries that provide HTTP interfaces to Urbit [here](https://github.com/urbit/awesome-urbit#http-apis-airlock).
5050
5151To learn more about how to work with Urbit's HTTP interface, follow [this
52−guide](/docs/arvo/eyre/using-eyre).
52+guide](/docs/arvo/eyre/external-api-ref).
5353
5454Alternatively, command-line interface (CLI) applications can be built using a
5555library called `shoe`, which you can learn more about
content/docs/development/project-repositories.md+7−6
@@ -4,7 +4,7 @@ weight = 30
44template = "doc.html"
55+++
66
7−Here's a breakdown of the various repositories that comprise the project. All of
7+Here's a breakdown of the various repositories the project comprises. All of
88our code is hosted on GitHub, so you can of course peruse it there at
99[https://github.com/urbit](https://github.com/urbit).
1010
@@ -14,19 +14,20 @@ Urbit OS, the Landscape interface and Vere are all contained in one monolithic
1414repository that can be found [here](https://github.com/urbit/urbit). The repo is
1515large, so here's some links to its various high-level components
1616
17−- [Arvo](https://github.com/urbit/urbit/tree/master/pkg/arvo): the part of the urbit repo that comprises Arvo, the Urbit OS.
17+- [Arvo](https://github.com/urbit/urbit/tree/master/pkg/arvo): the part of the
18+ urbit repo that contains Arvo, the Urbit OS.
1819- [Vere](https://github.com/urbit/urbit/tree/master/pkg/urbit): the part of the
19− urbit repo that comprises the C and Haskell interpreters.
20+ urbit repo that contains the C and Haskell interpreters.
2021- [Landscape
2122 interface](https://github.com/urbit/urbit/tree/master/pkg/interface): the part
2223 of the urbit repo that contains the interface code for Landscape.
2324 - [Issue Tracker](https://github.com/urbit/landscape/issues): the Landscape issue
2425 tracker is a separate repository.
25−
26+
2627### Urbit ID
2728
2829- [azimuth](https://github.com/urbit/azimuth): the public-key infrastructure
29− (PKI) that comprises Urbit ID, live on the Etheereum blockchain.
30+ (PKI) that implements Urbit ID, live on the Ethereum blockchain.
3031- [bridge](https://github.com/urbit/bridge): an application for interacting with
3132 Azimuth that can be accessed at [bridge.urbit.org](https://bridge.urbit.org).
3233- [urbit-key-generation](https://github.com/urbit/urbit-key-generation): a javascript library for key derivation and HD
@@ -40,7 +41,7 @@ large, so here's some links to its various high-level components
4041 website.
4142- [docs](https://github.com/urbit/docs): the source for the documentation that
4243 you're currently reading.
43− - *Note:* the documentation is loaded into the
44+ - _Note:_ the documentation is loaded into the
4445 [urbit.org](https://github.com/urbit/urbit.org) repo as a submodule.
4546
4647### Community
content/docs/hoon/reference/irregular.md+112−61
@@ -7,53 +7,62 @@ aliases = ["docs/reference/hoon-expressions/irregular/"]
77
88##### Reading guide
99
10−Headings contain runes, phonetics and tokens. Description contains a link to the docs and a short description of the rune. Both regular (R) and irregular (I) forms are given.
10+Headings contain runes, phonetics and tokens. Description contains a link to the
11+docs and a short description of the rune. Both regular and irregular forms are given.
1112
1213Want to `Ctrl-f` to find out the meaning of something weird you saw? Search for `\symbol`. ie `\?` or `\=`. It'll show you to the irregular forms that uses that symbol.
1314
14−## . dot (nock)
15+## `.` dot (nock)
1516
1617Anything Nock can do, Hoon can do also.
1718
18−### .+ dotlus
19+### `.+` dotlus
1920
2021[docs](/docs/hoon/reference/rune/dot#dotlus) \\+
22+
2123`[%dtls p=atom]`: increment an atom with Nock 4.
2224
23−R: `.+(p)`
24−I: `+(p)`
25+Regular: `.+(p)`
26+
27+Irregular: `+(p)`
2528
26−### .= dottis
29+### `.=` dottis
2730
2831[docs](/docs/hoon/reference/rune/dot#dottis) \\=
32+
2933`[%dtts p=hoon q=hoon]`: test for equality with Nock 5.
3034
31−R: `.=(p q)`
32−I: `=(p q)`
35+Regular: `.=(p q)`
3336
34−## ; mic (make)
37+Irregular: `=(p q)`
38+
39+## `;` mic (make)
3540
3641Miscellaneous useful macros.
3742
38−### ;: miccol
43+### `;:` miccol
3944
4045[docs](/docs/hoon/reference/rune/mic#miccol) \\:
46+
4147`[%mccl p=hoon q=(list hoon)]`: call a binary function as an n-ary function.
4248
43−R: `;:(p q)`
44−I: `:(p q)`
49+Regular: `;:(p q)`
50+
51+Irregular: `:(p q)`
4552
46−## : col (cells)
53+## `:` col (cells)
4754
4855The cell runes.
4956
50−### :- colhep
57+### `:-` colhep
58+
59+[docs](/docs/hoon/reference/rune/col#colhep) \\[\\]\\^\\+\\\`\\~
5160
52−[docs](/docs/hoon/reference/rune/col#colhep) \\[\\]\\^\\+\\\`\\~
5361`[%clhp p=hoon q=hoon]`: construct a cell (2-tuple).
5462
55−R: `:-(p q)`
56−I:
63+Regular: `:-(p q)`
64+
65+Irregular:
5766
5867```
5968 [a b] ==> :-(a b)
@@ -66,21 +75,24 @@ I:
6675 [a b]~ ==> [[a b] ~]
6776```
6877
69−## = tis (flow)
78+## `=` tis (flow)
7079
7180Flow hoons change the subject. All non-flow hoons (except cores) pass the subject down unchanged.
7281
73−### =< tisgal
82+### `=<` tisgal
7483
7584[docs](/docs/hoon/reference/rune/tis#tisgal) \\:
85+
7686`[%tsgl p=hoon q=hoon]`: compose two hoons, inverted.
7787
78−R: `=<(p q)`
79−I: `p:q`
88+Regular: `=<(p q)`
8089
81−## | bar (core)
90+Irregular: `p:q`
91+
92+## `|` bar (core)
8293
8394[docs](/docs/hoon/reference/rune/bar) \\$
95+
8496Core hoons are flow hoon.
8597
8698Technically not irregular syntax, but worth mentioning.
@@ -92,103 +104,143 @@ Technically not irregular syntax, but worth mentioning.
92104
93105The above runes produce a core with a single arm, named `$` ("buc"). We can recompute this arm with changes, useful for recursion among other things. Commonly used with the irregular syntax for `%=`, `:make`, like so: `$()`.
94106
95−## % cen (call)
107+## `%` cen (call)
96108
97109The invocation family of runes.
98110
99−### %= centis
111+### `%=` centis
112+
113+[docs](/docs/hoon/reference/rune/cen#centis) \\(\\)
100114
101−[docs](/docs/hoon/reference/rune/cen#centis) \\(\\)
102115`[%cnts p=wing q=(list (pair wing hoon))]`: take a wing with changes.
103116
104−R: `%=(p a 1)`
105−I: `p(a 1)`
117+Regular: `%=(p a 1)`
106118
107−### %~ censig
119+Irregular: `p(a 1)`
120+
121+### `%~` censig
108122
109123[docs](/docs/hoon/reference/rune/cen#censig) \\~
124+
110125`[%cnsg p=wing q=hoon r=hoon]`: call with multi-armed door.
111126
112−R: `%~(p q r)`
113−I: `~(p q r)`
127+Regular: `%~(p q r)`
128+
129+Irregular: `~(p q r)`
114130
115−### %- cenhep
131+### `%-` cenhep
116132
117133[docs](/docs/hoon/reference/rune/cen#cenhep) \\(\\)
134+
118135`[%cnhp p=hoon q=hoon]`: call a gate (function).
119136
120−R: `%-(p q)`
121−I: `(p q)`
137+Regular: `%-(p q)`
138+
139+Irregular: `(p q)`
122140
123141Note: `(p)` becomes `$:p` (`=<($ p)`), which behaves as you would expect (func call w/o args).
124142
125−## $ buc (mold)
143+## `$` buc (mold)
126144
127145A mold is a gate (function) that helps us build simple and rigorous data structures.
128146
129−### $? bucwut
147+### `$?` bucwut
130148
131149[docs](/docs/hoon/reference/rune/buc#bucwut) \\?
150+
132151`[%bcwt p=(list model)]`: mold which normalizes a general union.
133152
134−R: `$?(p)`
135−I: `?(p)`
153+Regular: `$?(p)`
136154
137−### $_ buccab
155+Irregular: `?(p)`
156+
157+### `$_` buccab
158+
159+[docs](/docs/hoon/reference/rune/buc#buccab) \\\_
138160
139−[docs](/docs/hoon/reference/rune/buc#buccab) \\_
140161`[%bccb p=value]`: mold which normalizes to an example.
141162
142−R: `$_(p)`
143−I: `_p`
163+Regular: `$_(p)`
164+
165+Irregular: `_p`
144166
145−## ? wut (test)
167+## `?` wut (test)
146168
147169Hoon has the usual branches and logical tests.
148170
149−### ?! wutzap
171+### `?!` wutzap
150172
151173[docs](/docs/hoon/reference/rune/wut#wutzap) \\!
174+
152175`[%wtzp p=hoon]`: logical not.
153176
154−R: `?!(p)`
155−I: `!(p)`
177+Regular: `?!(p)`
178+
179+Irregular: `!(p)`
156180
157−### ?& wutpam
181+### `?&` wutpam
158182
159183[docs](/docs/hoon/reference/rune/wut#wutpam) \\&
184+
160185`[%wtpm p=(list hoon)]`: logical and.
161186
162−R: `?&(p)`
163−I: `&(p)`
187+Regular: `?&(p)`
188+
189+Irregular: `&(p)`
164190
165−### ?| wutbar
191+### `?|` wutbar
166192
167193[docs](/docs/hoon/reference/rune/wut#wutbar) \\|
194+
168195`[%wtbr p=(list hoon)]`: logical or.
169196
170−R: `?|(p)`
171−I: `|(p)`
197+Regular: `?|(p)`
172198
173−## ^ ket (cast)
199+Irregular: `|(p)`
200+
201+## `^` ket (cast)
174202
175203Lets us adjust types without violating type constraints.
176204
177−### ^- kethep
205+### `^:` ketcol
206+
207+[docs](@/docs/hoon/reference/rune/ket.md#ketcol) \\,
208+
209+`[%ktcl p=spec]`: mold gate for type `p`.
210+
211+Regular: `^:(p)`
212+
213+Irregular: `,p`
214+
215+### `^-` kethep
178216
179217[docs](/docs/hoon/reference/rune/ket#kethep) \\\`
218+
180219`[%kthp p=model q=value]`: typecast by mold.
181220
182−R: `^-(p q)`
183−I: `` `p`q ``
221+Regular: `^-(p q)`
222+
223+Irregular: `` `p`q ``
224+
225+### `^*` kettar
184226
185−### ^= kettis
227+[docs](@/docs/hoon/reference/rune/ket.md#kettar) \\\*
228+
229+`[%kttr p=spec]`: produce bunt value of mold.
230+
231+Regular: `^*(p)`
232+
233+Irregular: `*p`
234+
235+### `^=` kettis
186236
187237[docs](/docs/hoon/reference/rune/ket#kettis) \\=
238+
188239`[%ktts p=toga q=value]`: name a value.
189240
190−R: `^=(p q)`
191−I: `p=q`
241+Regular: `^=(p q)`
242+
243+Irregular: `p=q`
192244
193245## Miscellaneous
194246
@@ -200,7 +252,6 @@ I: `p=q`
200252- `?` loobean.
201253- `~` null.
202254
203−
204255### Values
205256
206257\\~\\-\\.\\&\\|
@@ -220,6 +271,7 @@ See [%sand](/docs/hoon/reference/rune/constants#warm) for other irregular defini
220271### Limbs
221272
222273[docs](/docs/hoon/reference/limbs/limb) \\+\\.\\^
274+
223275`[%limb p=(each @ud [p=@ud q=@tas])]`: attribute of subject.
224276
225277- `+15` is slot 15
@@ -227,6 +279,7 @@ See [%sand](/docs/hoon/reference/rune/constants#warm) for other irregular defini
227279- `^a` is the `a` "of a higher scope", i.e. "resolve variable a, ignoring the first one found".
228280- `^^p` even higher, etc.
229281- 'Lark' syntax for slots / tree addressing:
282+
230283```
231284+1
232285+2 -
@@ -239,7 +292,6 @@ See [%sand](/docs/hoon/reference/rune/constants#warm) for other irregular defini
239292...
240293```
241294
242−
243295### Wings
244296
245297[docs](content/docs/hoon/reference/limbs/wing.md)
@@ -254,4 +306,3 @@ See [%sand](/docs/hoon/reference/rune/constants#warm) for other irregular defini
254306## Commentary
255307
256308In our in-house examples throughout our documentation, we use irregular forms instead of regular for the sake of verbosity. But remember with irregular forms: everything is just runes! Like magic. In general, irregular forms (usually) read better, but of course regular forms provide more information about what you're doing by showing you the full rune. Of course, it's up to you, the Hoon programmer, as to whether or not you want to use these.
257−
content/docs/system-overview/_index.md+13−13
@@ -6,11 +6,11 @@ template = "sections/docs/chapters.html"
66+++
77
88Urbit is a clean-slate software stack designed to implement an encrypted P2P
9−network of general-purpose personal servers. Each server on this network is a
9+network of general-purpose personal servers. Each server on this network is a
1010deterministic computer called an 'urbit' that runs on a Unix-based virtual
1111machine.
1212
13−The Urbit stack is primarily comprised of:
13+The Urbit stack primarily comprises:
1414
1515- [Arvo](/docs/system-overview/arvo): the functional operating system of
1616 each urbit, written in Hoon.
@@ -30,13 +30,13 @@ implemented [here](/docs/system-overview/cryptography).
3030## Anatomy of a personal server
3131
3232Your urbit is a deterministic computer in the sense that its state is a pure
33−function of its event history. Every event in this history is a
33+function of its event history. Every event in this history is a
3434[transaction](https://en.wikipedia.org/wiki/Transaction_processing); your
3535urbit's state is effectively an [ACID database](https://en.wikipedia.org/wiki/ACID).
3636
3737Because each urbit is deterministic we can describe its role appropriately in
3838purely functional terms: it maps an input event and the old urbit state to a
39−list of output actions and the subsequent state. This is the Urbit transition
39+list of output actions and the subsequent state. This is the Urbit transition
4040function.
4141
4242```
@@ -46,32 +46,32 @@ function.
4646For example, one input event could be a keystroke from the terminal, say
4747`[enter]` after having already typed `(add 2 2)`; and an output action could be
4848to print in the terminal window the resulting value of a computation performed
49−when the user hit `[enter]`, in this case `4`. The input event is stored in the
49+when the user hit `[enter]`, in this case `4`. The input event is stored in the
5050urbit's event history.
5151
5252Events always start from outside of your urbit, whether they're local to the
5353computer running the urbit (e.g., a keystroke in the terminal) or they originate
54−elsewhere (e.g., a packet received from another urbit). When an event is
54+elsewhere (e.g., a packet received from another urbit). When an event is
5555processed, various parts of the urbit state can be modified before the resulting
5656list of output actions is returned.
5757
5858Can output actions from your urbit cause side-effects in the outside world?
5959The answer had better be "yes," because a personal server without side effects
60−isn't useful for much. In another sense the answer had better be "no," or else
60+isn't useful for much. In another sense the answer had better be "no," or else
6161there is a risk of losing functional purity; your urbit cannot _guarantee_ that
62−the side effects in question actually occur. What's the solution?
62+the side effects in question actually occur. What's the solution?
6363
6464Each urbit is
6565[sandboxed](https://en.wikipedia.org/wiki/Sandbox_%28computer_security%29) in a
66−virtual machine, Vere, which runs on Unix. Code running in your urbit cannot
66+virtual machine, Vere, which runs on Unix. Code running in your urbit cannot
6767make Unix system calls or otherwise directly affect the underlying platform.
6868Strictly speaking, internal urbit code can only change internal urbit state; it
69−has no way of sending events outside of its runtime environment. Functional
69+has no way of sending events outside of its runtime environment. Functional
7070purity is preserved.
7171
7272In practical terms, however, you don't want your urbit to be an impotent
73−[brain in a vat](https://en.wikipedia.org/wiki/Brain_in_a_vat). That's why
74−Vere also serves as the intermediary between your urbit and Unix. Vere observes
73+[brain in a vat](https://en.wikipedia.org/wiki/Brain_in_a_vat). That's why
74+Vere also serves as the intermediary between your urbit and Unix. Vere observes
7575the list of output events, and when external action is called for makes the
76−appropriate system calls itself. When external events relevant to your urbit
76+appropriate system calls itself. When external events relevant to your urbit
7777occur in the Unix layer, Vere encodes and delivers them as input events.
content/docs/system-overview/cryptography.md+10−2
@@ -99,8 +99,8 @@ of private networking keys and retrieval of public networking keys utilized by
9999Ames. The Jael vane of planets, stars, and galaxies are responsible for
100100distributing the public keys of their moons (ultimately via Ames).
101101
102−`zuse` is the Hoon standard library. It contains cryptographic functions which
103−are utilized by Ames. All cryptographic primitives are
102+`zuse` is part of the standard library. It contains cryptographic functions
103+which are utilized by Ames. All cryptographic primitives are
104104[jetted](/docs/vere/jetting) in Vere with standard vetted implementations of
105105cryptographic libraries.
106106
@@ -114,3 +114,11 @@ infrastructure utilized by Urbit. `azimuth-tracker` obtains networking public
114114keys for planets, stars, and galaxies from this store, which are then stored in
115115Jael and utilized by Ames for end-to-end encrypted communication.
116116
117+### Additional documentation
118+
119+The following pages contained more detailed information about the cryptography
120+utilized by each of the system components.
121+
122+- [Ames](@/docs/arvo/ames/cryptography.md)
123+- [Zuse](@/docs/arvo/reference/cryptography.md)
124+- [Vere](@/docs/vere/cryptography.md)
content/docs/userspace/gall/gall.md+88−89
@@ -16,55 +16,55 @@ Urbit code lives in the following basic categories:
1616- Userspace agents (managed by Gall, permanent state)
1717- Userspace threads (managed by Spider, transient state)
1818
19−This lays out the framework for the third category: Agents.
19+This lays out the framework for the third category: Agents.
2020
2121An agent is a piece of software that is primarily focused on maintaining
22−and distributing a piece of state with a defined structure. It exposes
22+and distributing a piece of state with a defined structure. It exposes
2323an interface that lets programs read, subscribe to, and manipulate the
24−state. Every event happens in an atomic transaction, so the state is
25−never inconsistent. Since the state is permanent, when the agent is
24+state. Every event happens in an atomic transaction, so the state is
25+never inconsistent. Since the state is permanent, when the agent is
2626upgraded with a change to the structure of the state, the developer
2727provides a migration function from the old state type to the new state
2828type.
2929
3030It's not too far off to think of an agent as simply a database with
31−developer-defined logic. But an agent is significantly less constrained
32−than a database. Databases are usually tightly constrained in one or
31+developer-defined logic. But an agent is significantly less constrained
32+than a database. Databases are usually tightly constrained in one or
3333more ways because they need to provide certain guarantees (like
34−atomicity) or optimizations (like indexes). Urbit is a single-level
35−store, so atomicity comes for free. Many applications don't use
34+atomicity) or optimizations (like indexes). Urbit is a single-level
35+store, so atomicity comes for free. Many applications don't use
3636databases because they need relational indices; rather, they use them
37−for their guarantees around persistence. Some do need the indices,
37+for their guarantees around persistence. Some do need the indices,
3838though, and it's not hard to imagine an agent which provides a SQL-like
3939interface.
4040
4141On the other hand, an agent is also a lot like what many systems call a
42−"service". An agent is permanent and addressable -- a running program
42+"service". An agent is permanent and addressable -- a running program
4343can talk to an agent just by naming it. An agent can perform IO, unlike
44−most databases. This is a critical part of an agent: it performs IO
44+most databases. This is a critical part of an agent: it performs IO
4545along the same transaction boundaries as changes to its state, so if an
4646effect happens, you know that the associated state change has happened.
4747You should be careful, though, to avoid creating implicit non-atomicity
4848-- eg if it comes into an inconsistent state pending a response to an IO
4949action.
5050
51−But the best way to think about an agent is as a state machine. Like a
51+But the best way to think about an agent is as a state machine. Like a
5252state machine, any input could happen at any time, and it must react
53−coherently to that input. Ouput (effects) and the next state of the
53+coherently to that input. Ouput (effects) and the next state of the
5454machine are both pure functions of the previous state and the input
55−event. Of course, it's important to ensure there isn't an order of
55+event. Of course, it's important to ensure there isn't an order of
5656events that could cause your agent to enter an inconsistent state.
5757
5858We often think of state machines as finite state machines, but of course
5959in this instance, the state is not actually finite (though it should be
60−definable in a regular recursive data type).
60+definable in a regular recursive data type).
6161
6262## Specification
6363
6464An agent is defined as a [core](/docs/glossary/core/) with a set of [arms](/docs/glossary/arm/) to handle various
65−events. These handlers usually produce a list of effects and the next
66−state of the agent. The interface definition can be found in
67−`sys/zuse.hoon`, which at the time of writing is:
65+events. These handlers usually produce a list of effects and the next
66+state of the agent. The interface definition can be found in
67+`sys/lull.hoon`, which at the time of writing is:
6868
6969```hoon
7070++ agent
@@ -189,7 +189,7 @@ Here's a skeleton example of an implementation:
189189```
190190
191191We also supply a `default-agent` library, which is useful if you don't
192−want to handle some of the arms. Most of the above could also be
192+want to handle some of the arms. Most of the above could also be
193193implemented as:
194194
195195```hoon
@@ -219,35 +219,35 @@ implemented as:
219219--
220220```
221221
222−So, an agent is a core with 10 arms. The handlers correspond to
223−different sorts of input. We'll discuss each of these in detail, but
222+So, an agent is a core with 10 arms. The handlers correspond to
223+different sorts of input. We'll discuss each of these in detail, but
224224first a few general concepts.
225225
226226## Basic concepts
227227
228228### Interacting with an agent
229229
230−There are two basic ways programs can interact with an agent: you may
230+There are two basic ways programs can interact with an agent: you may
231231subscribe to data as described above, or you may "poke" an agent to send
232−it a command. Suppose there is an agent for a calendar service; then,
232+it a command. Suppose there is an agent for a calendar service; then,
233233pokes would likely include `%create-event`, `%modify-event`,
234234`%delete-event`, and `%change-time-zone` (along with assocated data).
235235Subscription paths could include `/next-event` and `/all-events`.
236236
237237Agents generally conform to CQRS -- pokes may change state, but
238−subscriptions generally shouldn't. In practice, there may be state
238+subscriptions generally shouldn't. In practice, there may be state
239239changes required to properly initialize the subscription, but these
240240shouldn't change the essential state of the agent.
241241
242242### Cards
243243
244244Most of the handlers produce a `(quip card agent:gall)`, which is just
245−`[(list card) agent:gall]`. The first allows us to produce effects, and
245+`[(list card) agent:gall]`. The first allows us to produce effects, and
246246the second allows us to maintain state.
247247
248−A card is one of two things: a `note` or a `gift`. You `%pass` `note`s
249−and you `%give` `gift`s. When you pass a `note`, you expect zero or more
250−responses; when you give a `gift`, you will not get a response. Since you
248+A card is one of two things: a `note` or a `gift`. You `%pass` `note`s
249+and you `%give` `gift`s. When you pass a `note`, you expect zero or more
250+responses; when you give a `gift`, you will not get a response. Since you
251251may get a response to a `note`, you tag it with a `wire` so that you can
252252identify the response.
253253
@@ -265,14 +265,14 @@ or
265265```
266266
267267When you give a `gift`, that's the end of the story, but when you pass a
268−`note`, you may get a response. If you do, then the response will come
269−tagged with the `wire` that you used to pass the `note`. It's generally
268+`note`, you may get a response. If you do, then the response will come
269+tagged with the `wire` that you used to pass the `note`. It's generally
270270good practice to make your `wire`s fairly unique within your agent, since
271271otherwise you may not be able to distinguish the responses.
272272
273273#### Notes
274274
275−An agent may pass `note`s to either Arvo or another agent. If the `note` is
275+An agent may pass `note`s to either Arvo or another agent. If the `note` is
276276to another agent, then it should usually be one of these:
277277
278278```hoon
@@ -282,23 +282,23 @@ to another agent, then it should usually be one of these:
282282```
283283
284284Note that to unsubscribe to a `path`, you must send the unsubscription on
285−the same `wire` that sent for the original subscription. Don't subscribe
285+the same `wire` that sent for the original subscription. Don't subscribe
286286to separate `path`s along the same `wire`, because then you can't properly
287287distinguish them for cancelling (besides not being able to distinguish
288−the subscription updates). In other words, besides letting *you*
288+the subscription updates). In other words, besides letting _you_
289289distinguish your `card`s, the `wire` also identifies requests for the system.
290290
291291If the `note` is not to another agent but to Arvo itself, then it is a
292292request to one of the vanes, which are kernel modules that provide
293−various system services, including IO. Here are some examples:
293+various system services, including IO. Here are some examples:
294294
295295```hoon
296296[%pass /my/wire %arvo %b %wait (add now.hid ~s10)]
297297```
298298
299299This is a request to the `%b` vane (Behn, the timer vane) to set a timer
300−for 10 seconds in the future. After 10 seconds, Behn will respond with
301−a `%wake` card, which you will recieve in `+on-arvo`. It will come back
300+for 10 seconds in the future. After 10 seconds, Behn will respond with
301+a `%wake` card, which you will recieve in `+on-arvo`. It will come back
302302on `/my/wire`.
303303
304304```hoon
@@ -308,7 +308,7 @@ on `/my/wire`.
308308```
309309
310310This is a request to the `%c` vane (Clay, the filesystem vane) to write
311−a file to `/my-file/txt` in the home desk. You will not receive a
311+a file to `/my-file/txt` in the home desk. You will not receive a
312312response to this `note`.
313313
314314```hoon
@@ -318,7 +318,7 @@ response to this `note`.
318318```
319319
320320This is a request to the `%c` vane to send us a `%writ` `card` whenever
321−`/my-file/txt` changes in the next hour. There may be many responses to
321+`/my-file/txt` changes in the next hour. There may be many responses to
322322this note if the file changes many times.
323323
324324```hoon
@@ -328,7 +328,7 @@ this note if the file changes many times.
328328```
329329
330330This is a request to the `%i` vane (Iris, the HTTP client vane) to make
331−a GET HTTP request to example.com. The response will come as an
331+a GET HTTP request to example.com. The response will come as an
332332`%http-response` card.
333333
334334#### Gifts
@@ -342,84 +342,83 @@ In contrast to the many possible `note`s, there are only two types of
342342```
343343
344344A subscription update is a new piece of subscription content for all
345−subscribers on a given `path`. If no `path` is given, then the update is
346−only given to the program that instigated this request. Typical use of
345+subscribers on a given `path`. If no `path` is given, then the update is
346+only given to the program that instigated this request. Typical use of
347347this mode is in `+on-watch` to give an initial update to a new
348348subscriber to get them up to date.
349349
350350A subscription close closes the subscription for all subscribers on a
351−given `path`. If no `path` is given, then the update is only given to the
352−program that instigated this request. Typical use of this mode would be
351+given `path`. If no `path` is given, then the update is only given to the
352+program that instigated this request. Typical use of this mode would be
353353in `+on-watch` to produce a single update to a subscription then close
354354the subscription.
355355
356356### Vases and cages
357357
358−A `vase` is a piece of dynamic data. Structurally, it's a pair of an
359−explicit reification of a type and an untyped [noun](/docs/glossary/noun/). This lets us
360−represent a value which has a type that isn't known at compile time. A
358+A `vase` is a piece of dynamic data. Structurally, it's a pair of an
359+explicit reification of a type and an untyped [noun](/docs/glossary/noun/). This lets us
360+represent a value which has a type that isn't known at compile time. A
361361vase has three operations:
362362
363363- `!>` is a unary rune that lifts a statically typed value to a
364− dynamically-typed `vase`. For example, `!>('hi')` gives `[#t/@t q=26.984]`.
364+ dynamically-typed `vase`. For example, `!>('hi')` gives `[#t/@t q=26.984]`.
365365
366366- `!<` is a binary rune that takes a mold and a dynamically typed `vase`
367− and reduces it to a statically typed value. If the `vase` does not in
367+ and reduces it to a statically typed value. If the `vase` does not in
368368 fact have the type of the mold you give it, then it nest-fails, else
369− it produces `value`. For example, `!<(@t !>('hi'))` produces `'hi'` while `!<(^ !>('hi'))` causes a nest fail..
369+ it produces `value`. For example, `!<(@t !>('hi'))` produces `'hi'` while `!<(^ !>('hi'))` causes a nest fail..
370370
371371- The compiler takes text and converts it to a `vase` of the compiled
372− code. Agents shouldn't need this directly, but Gall uses this to
373− compile agents to `vase`s, on which it calls `!<(agent:gall
374− compiled-agent-vase)`.
372+ code. Agents shouldn't need this directly, but Gall uses this to
373+ compile agents to `vase`s, on which it calls `!<(agent:gall compiled-agent-vase)`.
375374
376−A `cage` is simply a pair of a mark and a vase. A mark is a textual tag
375+A `cage` is simply a pair of a mark and a vase. A mark is a textual tag
377376that should correspond to the particular dynamic type in the vase.
378377
379378In agents, we use vases to represent types which Gall doesn't know about
380379when it was compiled, but which nevertheless need to go outside the
381−agent. In practice, there are three common cases:
380+agent. In practice, there are three common cases:
382381
383382- The data in a "poke" request is of a type that is defined by each
384− agent, so it must by dynamic. This is the input to `++on-poke` as well
383+ agent, so it must by dynamic. This is the input to `++on-poke` as well
385384 as the cage in the `%poke` case of the `%agent` note.
386385
387386- The data in a subscription update is defined by each agent, so it must
388− be dynamic. This is the cage in `%fact`, both when giving the update
387+ be dynamic. This is the cage in `%fact`, both when giving the update
389388 and in the input to `+on-agent`.
390389
391−- The state of an agent is also unique to each agent. Most of the time,
390+- The state of an agent is also unique to each agent. Most of the time,
392391 Gall doesn't interact directly with agent's state, but when upgrading
393392 an agent, it must pass the state of the old version of the agent to
394− the new version of the agent. This is the output of `+on-save` and
393+ the new version of the agent. This is the output of `+on-save` and
395394 the input to `+on-load`.
396395
397396### State
398397
399398In the definition of an agent, the entire core is wrapped with the `^|`
400−rune, which corresponds to the "iron" variance mode. This means it's
399+rune, which corresponds to the "iron" variance mode. This means it's
401400"contravariant" in the input, which allows Gall to write to the new bowl
402−on every event. It also means that the context of the core is opaque to
401+on every event. It also means that the context of the core is opaque to
403402Gall, which means you can store state in your context in whatever
404403structure you want.
405404
406405This is why most of the handler arms produce not just a list of cards
407−but also a new `agent:gall`. Usually, this will be the "same" agent in
406+but also a new `agent:gall`. Usually, this will be the "same" agent in
408407the sense that the code will be the same, but you may have changed the
409408state that's stored in its (opaque to Gall) context.
410409
411410The skeleton example above gives an example of keeping an atom as your
412−state. Define the state in the context of your agent core, then you can
411+state. Define the state in the context of your agent core, then you can
413412change it with `=.` or `%=`, as long as you produce the new version of
414413the agent core.
415414
416415When you upgrade an agent, you need to extract the state from your
417416opaque context and produce it to Gall as a dynamically typed vase.
418−Usually, this will be easy: just call `!>` on whatever state you wish
419−to preserve. This is `+on-save`.
417+Usually, this will be easy: just call `!>` on whatever state you wish
418+to preserve. This is `+on-save`.
420419
421420When the new agent is about to be started, Gall will call it with
422−`+on-load` with the vase just produced above. This allows you to ingest
421+`+on-load` with the vase just produced above. This allows you to ingest
423422your old state and continue right where you left off.
424423
425424If the type of your state hasn't changed, you can just
@@ -436,7 +435,7 @@ If it has changed, then it should look more like:
436435
437436It's useful to tag your state with a version number so that the
438437`+upgrade-state` function can take a tagged union of all your old state
439−types and upgrade from any of them to the current state type. For
438+types and upgrade from any of them to the current state type. For
440439example, it may have the following structure:
441440
442441```hoon
@@ -458,7 +457,7 @@ example, it may have the following structure:
458457### Bowl
459458
460459The core takes as input a `bowl`, which includes useful info like the
461−current ship, the current time, and a renewable source of entropy. This
460+current ship, the current time, and a renewable source of entropy. This
462461information is available to any of the handlers.
463462
464463## Arms
@@ -467,39 +466,39 @@ A description of each of the handler arms follows.
467466
468467### +on-init
469468
470−This arm is called once when the agent is started. It has no input and
469+This arm is called once when the agent is started. It has no input and
471470lets you perform any initial IO.
472471
473472### +on-save
474473
475−This arm is called immediately before the agent is upgraded. It
474+This arm is called immediately before the agent is upgraded. It
476475packages the permament state of the agent in a `vase` for the next version
477−of the agent. Unlike most handlers, this cannot produce effects.
476+of the agent. Unlike most handlers, this cannot produce effects.
478477
479478### +on-load
480479
481−This arm is called immediately after the agent is upgraded. It receives
480+This arm is called immediately after the agent is upgraded. It receives
482481a `vase` of the state of the previously-running version of the agent,
483482which allows it to cleanly upgrade from the old agent.
484483
485484### +on-poke
486485
487−This arm is called when the agent is "poked". The input is a `cage`, so
486+This arm is called when the agent is "poked". The input is a `cage`, so
488487it's a pair of a mark and a dynamic `vase`.
489488
490489### +on-watch
491490
492491This arm is called when a program wants to subscribe to the agent on a
493−particular `path`. The agent may or may not need to perform setup steps
494−to intialize the subscription. It may produce a `%give`
492+particular `path`. The agent may or may not need to perform setup steps
493+to intialize the subscription. It may produce a `%give`
495494`%subscription-result` to the subscriber to get it up to date, but after
496495this event is complete, it cannot give further updates to a specific
497−subscriber. It must give all further updates to all subscribers on a
496+subscriber. It must give all further updates to all subscribers on a
498497specific `path`.
499498
500499If this arm crashes, then the subscription is immediately terminated.
501500More specifcally, it never started -- the subscriber will receive a
502−negative `%watch-ack`. You may also produce an explicit `%kick` to
501+negative `%watch-ack`. You may also produce an explicit `%kick` to
503502close the subscription without crashing -- for example, you could
504503produce a single update followed by a `%kick`.
505504
@@ -507,23 +506,23 @@ produce a single update followed by a `%kick`.
507506
508507This arm is called when a program becomes unsubscribed to you.
509508Subscriptions may close because the subscriber intentionally
510−unsubscribed, but they also could be closed by an intermediary. For
509+unsubscribed, but they also could be closed by an intermediary. For
511510example, if a subscription is from another ship which is currently
512511unreachable, Ames may choose to close the subscription to avoid queueing
513−updates indefinitely. If the program crashes while processing an
514−update, this may also generate an unsubscription. You should consider
512+updates indefinitely. If the program crashes while processing an
513+update, this may also generate an unsubscription. You should consider
515514subscriptions to be closable at any time.
516515
517516### +on-peek
518517
519518This arm is called when a program reads from the agent's "scry"
520−namespace, which should be referentially transparent. Unlike most
521−handlers, this cannot perform IO, and it cannot change the state. All
519+namespace, which should be referentially transparent. Unlike most
520+handlers, this cannot perform IO, and it cannot change the state. All
522521it can do is produce a piece of data to the caller, or not.
523522
524523If this arm produces `[~ ~ data]`, then `data` is the value at the the
525−given `path`. If it produces `[~ ~]`, then there is no data at the given
526−`path` and never will be. If it produces `~`, then we don't know yet
524+given `path`. If it produces `[~ ~]`, then there is no data at the given
525+`path` and never will be. If it produces `~`, then we don't know yet
527526whether there is or will be data at the given `path`.
528527
529528### +on-agent
@@ -531,8 +530,8 @@ whether there is or will be data at the given `path`.
531530This arm is called to handle responses to `%give` moves to other agents.
532531It will be one of the following types of response:
533532
534−- `%poke-ack`: acknowledgment (positive or negative) of a poke. If the
535− value is `~`, then the poke succeeded. If the value is `[~ tang]`,
533+- `%poke-ack`: acknowledgment (positive or negative) of a poke. If the
534+ value is `~`, then the poke succeeded. If the value is `[~ tang]`,
536535 then the poke failed, and a printable explanation (e.g. a stack trace)
537536 is given in the `tang`.
538537
@@ -546,14 +545,14 @@ It will be one of the following types of response:
546545
547546### +on-arvo
548547
549−This arm is called to handle responses to `%pass` `move`s to vanes. The
548+This arm is called to handle responses to `%pass` `move`s to vanes. The
550549list of possible responses from the system is statically defined in
551−sys/zuse.hoon (grep for `+ sign-arvo`).
550+`sys/lull.hoon` (grep for `+$ sign-arvo`).
552551
553552### +on-fail
554553
555554If an error happens in `+on-poke`, the crash report goes into the
556−`%poke-ack` response. Similarly, if an error happens in
555+`%poke-ack` response. Similarly, if an error happens in
557556`+on-subscription`, the crash report goes into the `%watch-ack`
558−response. If a crash happens in any of the other handlers, the report
557+response. If a crash happens in any of the other handlers, the report
559558is passed into this arm.
content/docs/userspace/landscape/_index.md+1−1
@@ -15,4 +15,4 @@ An overview of how Landscape, our flagship client, is structured.
1515
1616## [API Reference](/docs/userspace/landscape/reference/)
1717
18−API documentation about specific agents that comprise Landscape.
18+API documentation about specific agents Landscape comprises.
content/docs/userspace/threads/http-api.mdnew file+73
@@ -0,0 +1,73 @@
1++++
2+title = "HTTP API"
3+weight = 2
4+template = "doc.html"
5++++
6+
7+Spider has an Eyre binding which allows threads to be run externally via [authenticated](@/docs/arvo/eyre/external-api-ref.md#authentication) HTTP POST requests.
8+
9+Spider is bound to the `/spider` URL path, and expects the requested URL to look like:
10+
11+```
12+http{s}://{host}/spider/{inputMark}/{threadName}/{outputMark}
13+```
14+
15+The `inputMark` is the `mark` the thread takes. The `threadName` is the name of the thread, e.g. `foo` for `/ted/foo/hoon`. The `outputMark` is the `mark` the thread produces. You may also include a file extension though it doesn't have an effect.
16+
17+When Spider receives an HTTP request, the following steps happen:
18+
19+1. It converts the raw body of the message to `json` using `de-json:html`
20+2. It creates a `tube:clay` (`mark` conversion gate) from `json` to whatever input `mark` you've specified and does the conversion.
21+3. It runs the specified thread and provides a `vase` of `(unit inputMark)` as the argument.
22+4. The thread does its thing and finally produces its result as a `vase` of `outputMark`.
23+5. Spider creates another `tube:clay` from the output `mark` to `json` and converts it.
24+6. It converts the `json` back into raw data suitable for the HTTP response body using `en-json:html`.
25+7. Finally, it composes the HTTP response and passes it back to Eyre which passes it on to the client.
26+
27+Thus, it's important to understand that the original HTTP request and final HTTP response must contain JSON data, and therefore the input & output `mark`s you specify must each have a `mark` file in `/mar` that includes a conversion method for `json -> inputMark` and `outputMark -> json` respectively.
28+
29+# Example
30+
31+Here we'll look at running Spider threads through Eyre.
32+
33+Here's an extremely simple thread that takes a `vase` of `(unit json)` and just returns the `json` in a new `vase`. You can save it in `/ted` and `|commit %home`:
34+
35+`eyre-thread.hoon`
36+
37+```hoon
38+/- spider
39+=, strand=strand:spider
40+^- thread:spider
41+|= arg=vase
42+=/ m (strand ,vase)
43+^- form:m
44+=/ =json
45+ (need !<((unit json) arg))
46+(pure:m !>(json))
47+```
48+
49+First we must obtain a session cookie by [authenticating](@/docs/arvo/eyre/examples.md#authenticating).
50+
51+Now we can try and run our thread. Spider is bound to the `/spider` URL path, and expects the rest of the path to be `/{inputMark}/{thread}/{outputMark}`. Our `{thread}` is called `eyre-thread`, and both its `{inputMark}` and `{outputMark}` are `json`, so our URL path will be `/spider/json/eyre-agent/json`. Our request will be an HTTP POST request and the body will be some `json`, in this case `[{"foo": "bar"}]`:
52+
53+```
54+curl -i --header "Content-Type: application/json" \
55+ --cookie "urbauth-~zod=0v6.h6t4q.2tkui.oeaqu.nihh9.i0qv6" \
56+ --request POST \
57+ --data '[{"foo": "bar"}]' \
58+ http://localhost:8080/spider/json/eyre-thread/json
59+```
60+
61+Spider will run the thread and the result will be returned through Eyre in the body of an HTTP response with a 200 status code:
62+
63+```
64+HTTP/1.1 200 ok
65+Date: Sun, 06 Jun 2021 05:32:45 GMT
66+Connection: keep-alive
67+Server: urbit/vere-1.5
68+set-cookie: urbauth-~zod=0v6.h6t4q.2tkui.oeaqu.nihh9.i0qv6; Path=/; Max-Age=604800
69+content-type: application/json
70+transfer-encoding: chunked
71+
72+[{"foo":"bar"}]
73+```
content/docs/vere/_index.md+7−2
@@ -6,6 +6,7 @@ template = "sections/docs/chapters.html"
66aliases = ["/docs/learn/vere/"]
77insert_anchor_links = "right"
88+++
9+
910The Nock runtime system, written in C.
1011
1112Keep reading if you're planning to work on the Urbit interpreter, you're a
@@ -15,7 +16,7 @@ you've seen the actual structs.
1516## [C runtime system](/docs/vere/runtime)
1617
1718The Urbit interpreter is built on a Nock runtime system written
18−in C, `u3`. This section is a relatively complete description.
19+in C, `u3`. This section is a relatively complete description.
1920
2021## [c3: C in Urbit](/docs/vere/c)
2122
@@ -25,7 +26,7 @@ in Urbit.
2526## [u3: Land of nouns](/docs/vere/nouns)
2627
2728The division between `c3` and `u3` is that you could theoretically
28−imagine using `c3` as just a generic C environment. Anything to do
29+imagine using `c3` as just a generic C environment. Anything to do
2930with nouns is in `u3`.
3031
3132## [u3: API overview by prefix](/docs/vere/api)
@@ -35,3 +36,7 @@ A walkthrough of each of the `u3` modules.
3536## [How to write a jet](/docs/vere/jetting)
3637
3738A jetting guide by for new Urbit developers.
39+
40+## [Cryptography](@/docs/vere/cryptography.md)
41+
42+References on the cryptography libraries utilized by jets.
content/docs/vere/cryptography.mdnew file+43
@@ -0,0 +1,43 @@
1++++
2+title = "Cryptography"
3+weight = 6
4+template = "doc.html"
5++++
6+
7+All cryptographic primitives utilized by Arvo are
8+[jetted](@/docs/vere/jetting.md). This is done for performance-related reasons
9+in other parts of the system, but for cryptography this is also extremely
10+important because it allows us to utilize standard reference implementations for
11+the primitives written in C.
12+
13+All jets related to encryption may be found in `pkg/urbit/jets/e/`.
14+
15+In this section we review what specific implementations are utilized. At the
16+moment, only libraries directly related to Ames are documented here, though we
17+note that there are jets for other cryptographic functions such as the [SHA
18+Hash Family](@/docs/hoon/reference/stdlib/3d.md) as well.
19+
20+### Ed25519 {#ed}
21+
22+Urbit implements [Ed25519](http://ed25519.cr.yp.to/) based on the SUPERCOP
23+"ref10" implementation. Additionally there is key exchanging and scalar addition
24+included to further aid building a PKI using Ed25519. All code is licensed under
25+the permissive zlib license.
26+
27+All code is pure ANSI C without any dependencies, except for the random seed
28+generation which uses standard OS cryptography APIs (CryptGenRandom on Windows,
29+`/dev/urandom` on nix).
30+
31+### AES-SIV {#aes}
32+
33+The library we utilize for AES-SIV is an
34+[RFC5297](https://tools.ietf.org/html/rfc5297)-compliant C implementation of
35+AES-SIV written by Daniel Franke on behalf of [Akamai
36+Technologies](https://www.akamai.com). It is published under the [Apache License
37+(v2.0)](https://www.apache.org/licenses/LICENSE-2.0). It uses OpenSSL for the
38+underlying [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) and
39+[CMAC](https://en.wikipedia.org/wiki/One-key_MAC) implementations and follows a
40+similar interface style.
41+
42+While the jets are found in `pkg/urbit/jets/e`, the statically-linked package is
43+found at `pkg/libas_siv/`.