nervur 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/CONTRIBUTING.md +13 -0
  2. package/LICENSE +55 -202
  3. package/NOTICE +3 -8
  4. package/README.md +14 -156
  5. package/RELEASING.md +15 -0
  6. package/SECURITY.md +9 -0
  7. package/bin/nervur.js +6 -0
  8. package/package.json +26 -81
  9. package/AUTHORING.md +0 -935
  10. package/COMMAND.md +0 -179
  11. package/FACES.md +0 -280
  12. package/FACULTIES.md +0 -578
  13. package/GROUNDS.md +0 -315
  14. package/KIT-SPEC.md +0 -304
  15. package/WORLD.md +0 -195
  16. package/dist/app/app-ground.d.ts +0 -18
  17. package/dist/app/app-ground.js +0 -23
  18. package/dist/app/index.d.ts +0 -2
  19. package/dist/app/index.js +0 -5
  20. package/dist/app/native.d.ts +0 -11
  21. package/dist/app/native.js +0 -13
  22. package/dist/being/being.d.ts +0 -306
  23. package/dist/being/being.js +0 -20
  24. package/dist/being/covers.d.ts +0 -9
  25. package/dist/being/covers.js +0 -21
  26. package/dist/being/index.d.ts +0 -4
  27. package/dist/being/index.js +0 -6
  28. package/dist/being/need.d.ts +0 -49
  29. package/dist/being/need.js +0 -33
  30. package/dist/being/schema.d.ts +0 -100
  31. package/dist/being/schema.js +0 -132
  32. package/dist/being/table.d.ts +0 -48
  33. package/dist/being/table.js +0 -344
  34. package/dist/bench/bench-ground.d.ts +0 -73
  35. package/dist/bench/bench-ground.js +0 -153
  36. package/dist/bench/bench.d.ts +0 -101
  37. package/dist/bench/bench.js +0 -368
  38. package/dist/bench/fake-clock.d.ts +0 -17
  39. package/dist/bench/fake-clock.js +0 -34
  40. package/dist/bench/fake-memory.d.ts +0 -16
  41. package/dist/bench/fake-memory.js +0 -46
  42. package/dist/bench/fake-network.d.ts +0 -66
  43. package/dist/bench/fake-network.js +0 -222
  44. package/dist/bench/fake-unlock.d.ts +0 -6
  45. package/dist/bench/fake-unlock.js +0 -10
  46. package/dist/bench/index.d.ts +0 -3
  47. package/dist/bench/index.js +0 -5
  48. package/dist/bench/seeded.d.ts +0 -11
  49. package/dist/bench/seeded.js +0 -37
  50. package/dist/bench/settle.d.ts +0 -2
  51. package/dist/bench/settle.js +0 -49
  52. package/dist/bench/stewards.d.ts +0 -169
  53. package/dist/bench/stewards.js +0 -128
  54. package/dist/bodies/class-list.d.ts +0 -14
  55. package/dist/bodies/class-list.js +0 -33
  56. package/dist/bodies/joined-carry.d.ts +0 -29
  57. package/dist/bodies/joined-carry.js +0 -48
  58. package/dist/bodies/kept.d.ts +0 -44
  59. package/dist/bodies/kept.js +0 -91
  60. package/dist/bodies/noble-crypto.d.ts +0 -22
  61. package/dist/bodies/noble-crypto.js +0 -88
  62. package/dist/bodies/seed-keys.d.ts +0 -10
  63. package/dist/bodies/seed-keys.js +0 -42
  64. package/dist/bodies/strict-tools.d.ts +0 -10
  65. package/dist/bodies/strict-tools.js +0 -306
  66. package/dist/bodies/vouch.d.ts +0 -20
  67. package/dist/bodies/vouch.js +0 -71
  68. package/dist/bodies/web-carry.d.ts +0 -72
  69. package/dist/bodies/web-carry.js +0 -245
  70. package/dist/bodies/web-clock.d.ts +0 -12
  71. package/dist/bodies/web-clock.js +0 -33
  72. package/dist/browser/browser-ground.d.ts +0 -76
  73. package/dist/browser/browser-ground.js +0 -294
  74. package/dist/browser/index.d.ts +0 -4
  75. package/dist/browser/index.js +0 -7
  76. package/dist/browser/indexeddb-memory.d.ts +0 -17
  77. package/dist/browser/indexeddb-memory.js +0 -97
  78. package/dist/browser/locked-unlock.d.ts +0 -24
  79. package/dist/browser/locked-unlock.js +0 -85
  80. package/dist/browser/origin-classes.d.ts +0 -7
  81. package/dist/browser/origin-classes.js +0 -31
  82. package/dist/edge/durable-clock.d.ts +0 -19
  83. package/dist/edge/durable-clock.js +0 -61
  84. package/dist/edge/durable-memory.d.ts +0 -5
  85. package/dist/edge/durable-memory.js +0 -11
  86. package/dist/edge/durable.d.ts +0 -18
  87. package/dist/edge/durable.js +0 -24
  88. package/dist/edge/edge-ground.d.ts +0 -49
  89. package/dist/edge/edge-ground.js +0 -223
  90. package/dist/edge/index.d.ts +0 -7
  91. package/dist/edge/index.js +0 -9
  92. package/dist/edge/native-crypto.d.ts +0 -8
  93. package/dist/edge/native-crypto.js +0 -102
  94. package/dist/edge/secret-unlock.d.ts +0 -7
  95. package/dist/edge/secret-unlock.js +0 -13
  96. package/dist/edge/socket-carry.d.ts +0 -39
  97. package/dist/edge/socket-carry.js +0 -111
  98. package/dist/foundation.d.ts +0 -162
  99. package/dist/foundation.js +0 -4
  100. package/dist/ground/dock.d.ts +0 -1460
  101. package/dist/ground/dock.js +0 -1159
  102. package/dist/ground/ground.d.ts +0 -239
  103. package/dist/ground/ground.js +0 -787
  104. package/dist/ground/views.d.ts +0 -76
  105. package/dist/ground/views.js +0 -208
  106. package/dist/house/crossing.d.ts +0 -50
  107. package/dist/house/crossing.js +0 -153
  108. package/dist/house/house.d.ts +0 -88
  109. package/dist/house/house.js +0 -2069
  110. package/dist/house/rows-shape.d.ts +0 -110
  111. package/dist/house/rows-shape.js +0 -12
  112. package/dist/house/rows.d.ts +0 -27
  113. package/dist/house/rows.js +0 -185
  114. package/dist/index.d.ts +0 -33
  115. package/dist/index.js +0 -29
  116. package/dist/node/bridge.d.ts +0 -20
  117. package/dist/node/bridge.js +0 -284
  118. package/dist/node/cli.d.ts +0 -2
  119. package/dist/node/cli.js +0 -225
  120. package/dist/node/file-memory.d.ts +0 -13
  121. package/dist/node/file-memory.js +0 -86
  122. package/dist/node/folder-classes.d.ts +0 -5
  123. package/dist/node/folder-classes.js +0 -40
  124. package/dist/node/gone.d.ts +0 -2
  125. package/dist/node/gone.js +0 -7
  126. package/dist/node/hand.d.ts +0 -39
  127. package/dist/node/hand.js +0 -107
  128. package/dist/node/http.d.ts +0 -11
  129. package/dist/node/http.js +0 -90
  130. package/dist/node/index.d.ts +0 -11
  131. package/dist/node/index.js +0 -13
  132. package/dist/node/ledger-memory.d.ts +0 -17
  133. package/dist/node/ledger-memory.js +0 -152
  134. package/dist/node/lock.d.ts +0 -10
  135. package/dist/node/lock.js +0 -78
  136. package/dist/node/node-ground.d.ts +0 -26
  137. package/dist/node/node-ground.js +0 -228
  138. package/dist/node/notify.d.ts +0 -1
  139. package/dist/node/notify.js +0 -18
  140. package/dist/node/shell.d.ts +0 -11
  141. package/dist/node/shell.js +0 -35
  142. package/dist/node/sync-folder.d.ts +0 -6
  143. package/dist/node/sync-folder.js +0 -18
  144. package/dist/node/tcp-carry.d.ts +0 -42
  145. package/dist/node/tcp-carry.js +0 -193
  146. package/dist/node/unlock.d.ts +0 -17
  147. package/dist/node/unlock.js +0 -86
  148. package/dist/node/websocket.d.ts +0 -12
  149. package/dist/node/websocket.js +0 -134
  150. package/dist/quo/frame.d.ts +0 -33
  151. package/dist/quo/frame.js +0 -92
  152. package/dist/quo/index.d.ts +0 -1
  153. package/dist/quo/index.js +0 -5
  154. package/dist/quo/room.d.ts +0 -154
  155. package/dist/quo/room.js +0 -362
  156. package/dist/serve/index.d.ts +0 -45
  157. package/dist/serve/index.js +0 -71
package/GROUNDS.md DELETED
@@ -1,315 +0,0 @@
1
- # Grounds
2
-
3
- A ground is the process houses run in. The library ships one for each
4
- terrain, and you write none. You give it one key, and through its hand
5
- you tell it which faculties to stand and which houses to open. This
6
- guide says what every ground does, then what each one adds. [Writing
7
- for nervur](AUTHORING.md) builds the shop this guide runs, and [the
8
- command](COMMAND.md) drives a ground on your machine.
9
-
10
- ## What every ground does
11
-
12
- **It holds one key outside itself.** The key is sixty-four hex digits,
13
- kept by what the ground stands on: a file, a keychain, a Worker's
14
- secret. The part of a ground that answers it is its unlock. Everything
15
- else the ground keeps is sealed under that key.
16
-
17
- **It unpacks in layers, each a faculty.** Every faculty has one
18
- lifecycle. A registry holds faculties by name, each an object `{ takes?,
19
- up, install? }`. Standing one raises it by its `up` into a body, the
20
- living instance houses and other bodies use. `install` does the slow
21
- work once for each entry, and a body's `down` lets go of what its `up`
22
- opened.
23
-
24
- | Layer | Its faculties | What they are |
25
- | --- | --- | --- |
26
- | primordial | the memory, the unlock, crypto, tools, the clock | the host's, read from the environment alone |
27
- | the ground's work | `ground` | the library's, offered to the dock alone |
28
- | the dock | a house of the library's beings | the drawer, and the hand's one road |
29
- | the ladder | the terrain's defaults and your entries | carries, code, and every custom faculty |
30
- | the hand | a socket, a key, a channel | the owner's reach, up last and down first |
31
-
32
- **It keeps its drawer as cells of the dock's beings.** The dock is a
33
- house every ground stands, and its beings are the library's. A twin
34
- stands for each faculty entry, a being for each house, and one for each
35
- secret. Their cells hold every entry, what each faculty installed, each
36
- house's seed and ward, every secret, and the ground's bound on every
37
- ask. No row of the ground's stands beside them.
38
-
39
- **Every name an entry gives is a standing.** A house's code, its memory
40
- and the faculties it uses, and a faculty's registry, its callees and its
41
- secrets, are relations between those beings. The dock's steward
42
- introduces each, and her notes name the grant. An entry that names a
43
- faculty or a secret the dock does not hold is refused, and nothing
44
- lands.
45
-
46
- **Its houses keep their places in the same memory.** The dock, each
47
- house and each faculty sees a view of the ground's memory under a prefix
48
- of its own. A house seals its own rows, and the ground seals each
49
- faculty's. So what rests on the disk is ciphertext, and copying the key,
50
- the memory and the code moves the whole ground. A memory the key opens
51
- no dock in is refused.
52
-
53
- **It stands its bodies on a ladder.** The ground's own registry is its
54
- terrain's. A body may carry a registry of its own, and the faculties an
55
- entry raises `from` it stand after it. A body stands after each body its
56
- entry names in `faculties`, whose objects its `up` receives. A body that
57
- fails to stand stays down and says why, and the ground boots beside it.
58
-
59
- **Its terrain names default entries, and yours win.** Each ground stands
60
- its carries and its bodies of code from entries of its own. Its one
61
- clock is primordial, which the dock and every house receive.
62
- An entry you land under the same name stands in its place.
63
-
64
- ```text
65
- recipe { from: 'folder', make: 'module', args: { at: 'recipe.ts' } }
66
- payments { from: 'recipe', make: 'payments', secrets: ['stripe-key'], kinds: ['com.acme.order'] }
67
- ```
68
-
69
- **It opens each house on its entry.** An entry names the body that
70
- serves the house's code, the custom faculties it may use, and the
71
- longest any of its asks may run. It names a body serving memory only
72
- where the house keeps its places apart from the ground's memory. Beside
73
- each body's name, it holds the args that body hands this house.
74
-
75
- ```text
76
- shop { classes: { faculty: 'folder', at: 'shop' }, faculties: ['payments'], wait: 60000 }
77
- ```
78
-
79
- **A change answers what stands, and an error means nothing landed.**
80
- Adding or updating a faculty answers why its body is down, where it is.
81
- Adding or updating a house answers its ward, or why it stays closed.
82
- The entry lands either way, and the hand mends it later.
83
-
84
- **It updates an entry in one write.** `update` lands the new entry over
85
- the old. A house closes and opens again on it, as the same ward. A body
86
- goes down, installs where its entry moved, and goes up, and each house
87
- naming it opens again. `restart` takes a body down and up on its entry.
88
-
89
- **It grants a faculty in two steps.** A house uses only the faculties its
90
- entry names. Inside it, a being holds one only where the faculty's entry
91
- names her class in `kinds`, or where it names none. So a raw program
92
- reaches one house and one class inside it.
93
-
94
- **It hands each faculty its secrets.** A secret is set through the hand
95
- and kept in a being's cells. A faculty's entry names the secrets its
96
- `up` receives, and no other code reads one. The hand lists their names
97
- and the entries that name each, and never a value. A secret's cells are
98
- shown to no one, and a changed secret reaches a body when it goes up
99
- again.
100
-
101
- **It holds each entry to what its faculty takes.** A faculty declares
102
- `takes`: a schema its args meet, and the secrets its entry must name.
103
- The hand refuses an entry that fails it, or that names a secret not
104
- kept, and says what failed. `facultiesCatalog` shows every faculty the
105
- ground can raise, and what each takes.
106
-
107
- **It hooks every door and runs one listener.** Each house's door goes to
108
- the ground's carry, which also delivers between the ground's own houses
109
- without touching the network. Everything that speaks HTTP, Quo over the
110
- web and every face, is a handler on one listener. A faculty stood while
111
- the ground runs is served at once.
112
-
113
- **The dock's steward reaches the ground through two faculties.** The
114
- `ground` faculty raises and lowers bodies, opens and closes houses,
115
- shows the catalogue and moves a house's places. It is offered to the
116
- dock's beings alone. The `shell` runs a command on the ground's machine,
117
- where the terrain has one. The dock is offered it as any house is
118
- offered a body. Its steward stands on the shell's twin, and the twin's
119
- entry grants it to the dock's shell being alone. No entry names, makes
120
- or grants either.
121
-
122
- **A boot writes only what moved.** Each twin raises its body by a read,
123
- and her cells are written only where what came of it differs. So a wake
124
- that finds nothing changed writes nothing.
125
-
126
- **It serves its owner's hand, and the hand has one road.** The hand
127
- answers `describe`, and otherwise asks a being of the dock or of a house
128
- as `root`. A request that names a house asks a being there. One that
129
- names none asks the dock's steward. `describe` shows her asks, every
130
- faculty with its methods or why it is down, and every house.
131
-
132
- | The dock's asks | What they do | Who asks them |
133
- | --- | --- | --- |
134
- | `housesAdd`, `housesUpdate`, `housesRemove`, `housesList` | the houses | `root`, and a pilot |
135
- | `facultiesAdd`, `facultiesUpdate`, `facultiesRestart`, `facultiesRemove`, `facultiesList` | the faculties | `root`, and a pilot |
136
- | `facultiesCatalog` | every faculty the ground can raise, and what it takes | `root`, and a pilot |
137
- | `waitSet`, `waitShow` | the ground's bound on every ask | `root`, and a pilot |
138
- | `secretsSet`, `secretsRemove`, `secretsList` | the secrets | `root` alone |
139
- | `movesOut`, `movesIn` | a house moved between grounds | `root` alone |
140
- | `callFaculty` | a faculty's method, called by name | `root` alone |
141
- | `shellRun` | a command on the ground's machine | `root` alone |
142
- | `pilotsInvite`, `pilotsDismiss`, `pilotsList` | who pilots the ground | `root` alone |
143
- | `boot` | the ladder stood and every house opened, as each boot asks | `root` alone |
144
-
145
- **An ask of the dock is safe to send twice.** A request may carry
146
- `call`, its call id. The same id sent again answers what the first
147
- answered, and runs nothing twice.
148
-
149
- **It lets a pilot possess it from afar.** `pilotsInvite` mints an
150
- invitation to the dock's steward, and the owner hands it to one being.
151
- That being then holds a standing on the dock, and asks the houses and
152
- faculties asks through it. Her class reaches them typed with
153
- `this.held(id, DockPilot)`, the need `nervur` exports. Secrets, moves,
154
- the shell and faculties' methods stay the hand's alone. A secret passes
155
- through `secretsSet`, which answers nothing, so no answer holds one.
156
-
157
- **It moves a house by its seed and its memory.** `movesOut` takes a
158
- house out as its seed and every place of its memory, and another ground
159
- takes them in with `movesIn`. The house keeps its identity, so every
160
- relation still answers and no far house notices.
161
-
162
- ## The five grounds
163
-
164
- | Ground | Where it runs | When it wakes | Its unlock | Its memory | Its hand |
165
- | --- | --- | --- | --- | --- | --- |
166
- | NodeGround | a server, a desktop, a Pi | always on | a key file, or the macOS keychain | a ledger in its folder | a socket in its folder |
167
- | EdgeGround | a Cloudflare Worker and its Durable Object | per request, per message, per alarm | the Worker's secret | the object's storage | a key the Worker holds |
168
- | BrowserGround | a page or its service worker | while a tab is open, and by push | a key sealed under one the browser never hands out | IndexedDB | a channel between the origin's tabs |
169
- | AppGround | an iOS or Android app's web view | per launch, and by push | the Keychain or the Keystore | the app's native store | a channel, as in a page |
170
- | BenchGround | memory, in a test | as the test moves its clock | a key drawn from the bench's seed | memory in the process | the test's own |
171
-
172
- The same class runs unchanged on every row. What differs is the bodies
173
- each ground hands its houses.
174
-
175
- ## NodeGround
176
-
177
- **`nervur up <folder>` runs one.** The folder holds your code: a folder
178
- for each house, and each module or program your entries name. Its
179
- `state/` holds the key, the ground's ledger and the hand's socket. A
180
- house's folder has an `index` that exports its `steward`, and `public`
181
- and `beings` where it has them, as [Writing for nervur](AUTHORING.md)
182
- shows. The ground's folder is an ES module package, so its
183
- `package.json` says `"type": "module"`. It listens on TCP and, where a
184
- port is set, on the web. [The command](COMMAND.md) lists its settings
185
- and runs its hand.
186
-
187
- **Its registry holds its terrain's faculties.** `folder` serves each
188
- house its classes from a folder inside the code folder its args name.
189
- Its body carries a registry of two more, rooted there. `module` imports
190
- a module as a registry, whose `faculties` export holds `{ up, install?
191
- }` by name. `bridge` starts a program, in any language, and hands it the
192
- secrets its entry names as its environment. An entry stands either with
193
- `from: 'folder'`. `tcp` and `web` are its carries, `listener` its one
194
- listener, and `shell` its shell. Its clock is the library's, and
195
- primordial.
196
-
197
- **Its code gives the default entries.** `folder`, `listener`, `tcp`,
198
- `web` and `shell` stand from entries the library fixes. TCP
199
- listens on the loopback at 9110, so nothing beyond the machine reaches
200
- a new ground. A server names its bind through the hand. The web names
201
- `listener` in its `faculties` and listens on no port. An entry of the
202
- same name you land stands in their place, so a port changes through the
203
- hand. Name
204
- `listener` there too, since the web serves the listener it calls.
205
-
206
- **A port another process holds keeps that carry down with why.** The
207
- ground boots beside it until the hand moves the port. A `tcp` entry
208
- whose args name no port only dials, and its invitations name no TCP
209
- address. Its environment names only `NERVUR_STATE`, `NERVUR_UNLOCK` and
210
- `NERVUR_HAND`.
211
-
212
- **Its key rests in `state/key`, its owner's alone.** A key file others
213
- may read is refused, as ssh refuses a key. On macOS,
214
- `NERVUR_UNLOCK=keychain:<account>` keeps the key in the keychain
215
- instead. Keep `state/` as you keep an ssh key: whoever holds the key and
216
- the ledger holds the ground.
217
-
218
- **It keeps its memory as a ledger, which holds the folder's lock.** Every
219
- write is one line, chained to the line before it and synced before it
220
- counts. A ledger edited anywhere but its end is refused. A witness file
221
- kept on another disk refuses a restored copy that is behind. While the
222
- ledger stands, a second ground on the same state is refused.
223
-
224
- **Its shell runs a command for the hand alone.** `nervur shell run --
225
- <command>` runs it in the code folder, and answers its exit code and
226
- what it printed. Its environment holds `PATH`, `HOME` and a few more of
227
- the process's, and never a secret or a `NERVUR_` variable. No pilot and
228
- no being reaches it.
229
-
230
- **It runs a program as a faculty, in any language.** The bridge starts a
231
- program and speaks one JSON value a line on its standard streams. The
232
- program keeps what it must in the faculty's sealed memory, through lines
233
- of its own. [Writing a faculty](FACULTIES.md) teaches it.
234
-
235
- ## EdgeGround
236
-
237
- **An edge is one Durable Object, woken per event.** The Worker hands
238
- every request to the one object its ground's name gives. At each wake
239
- the ground boots again, and a house opens only when a box for it arrives
240
- or the hand names it.
241
-
242
- **Its Worker's module is two lines over your code.**
243
-
244
- ```ts
245
- // worker.ts
246
- import { EdgeGround } from 'nervur/edge';
247
- import * as shop from './classes/index.ts';
248
- import * as recipe from './recipe.ts';
249
-
250
- export const Ground = EdgeGround.object({ registry: recipe, code: { shop } });
251
-
252
- export default EdgeGround.worker();
253
- ```
254
-
255
- The Worker binds the object's class as `GROUND`, with SQLite storage.
256
- `registry` joins the terrain's own, so an entry raises `payments` with
257
- no `from`. A house's entry names its code with `classes: { faculty:
258
- 'bundle', at: 'shop' }`.
259
-
260
- **Its Worker holds two secrets and nothing else.**
261
-
262
- | Variable | What it names |
263
- | --- | --- |
264
- | `NERVUR_SECRET` | the ground's key, sixty-four hex digits; set as a secret |
265
- | `NERVUR_HAND` | the key its hand answers; set as a secret |
266
-
267
- A Worker learns no name it is reached by, so it writes only the
268
- addresses its `web` entry names, the held line first. Name them through
269
- the hand with `facultiesUpdate`, as `addresses` in the args of `web`,
270
- beside its `origins` and `allowPrivate`, and the dock keeps them.
271
- Every ask runs a minute at most, and `waitSet` keeps a shorter bound.
272
- Its faculties take their secrets from the dock, as on every ground. It
273
- has no shell.
274
-
275
- **Its hand answers its key alone.** The hand is `POST /nervur/hand`, with
276
- the key as a bearer token and one request as the body. Every other
277
- request there, and every request to an edge that sets no key, finds
278
- nothing.
279
-
280
- **It is deployed by a faculty, never by hand.** A faculty on your
281
- NodeGround holds the account. It builds the module, uploads it with the
282
- two secrets, keeps them, and reaches the hand. The library ships none,
283
- since a deploy is a choice of yours. The first deploy is that faculty
284
- called through your NodeGround's hand, and every later one is your pilot
285
- being's.
286
-
287
- **Its held lines hibernate.** A page or a device holds a WebSocket on the
288
- edge, the platform keeps it while the object sleeps, and a message wakes
289
- the object. A watch held on that line answers the moment the change lands.
290
-
291
- ## BrowserGround and AppGround
292
-
293
- **A BrowserGround is one ground for its origin.** Every tab and the
294
- service worker of an origin share it. The tab holding a Web Lock runs
295
- the ground, and its hand answers every other tab over a channel. It
296
- only dials, so it answers no face. Whoever serves the origin's script
297
- possesses the ground, so its origin serves nothing else.
298
- [The package's start](README.md) opens one in a page.
299
-
300
- **Its registry is the one the page hands.** `BrowserGround.open({
301
- registry })` joins it to the terrain's own, whose faculty `origin`
302
- serves each house its classes from the origin.
303
-
304
- **An AppGround is a BrowserGround with the shell's bodies.** The app's
305
- native shell hands in two small interfaces, one for secrets and one for
306
- a store, and the library holds the rest. The ground's key rests in the
307
- secret store.
308
-
309
- ## BenchGround
310
-
311
- **A BenchGround runs a world in memory.** A `FakeNetwork` joins several,
312
- gives them names as DNS does, and carries every box between them on one
313
- clock the test moves. It cuts, slows, drops and repeats boxes, and turns
314
- a ground off and on. So one test proves the same classes at every
315
- distance. [Writing for nervur](AUTHORING.md) tests the shop on it.
package/KIT-SPEC.md DELETED
@@ -1,304 +0,0 @@
1
- # nervur's answers to KIT-SPEC
2
-
3
- This document answers, for `nervur`, every question that Quo's `KIT-SPEC.md`
4
- asks of a kit. Quo's spec, `SPEC.md`, and `KIT-SPEC.md` stand in
5
- [razvangherghina/quo](https://github.com/razvangherghina/quo), and every
6
- term below is the term they define. Quo's verifier judges nervur's Quo
7
- layer as a door, an asker, a TCP listener and a TCP dialer. It passes all
8
- four. Each answer states what the code of this version does.
9
-
10
- ## What stands behind a door
11
-
12
- **Question 1.** A house stands behind each door, and holds one ward. A
13
- house holds beings. A being is an instance of a class a developer writes,
14
- with JSON cells and named asks. A ground is the script that opens a house.
15
- It hands each arrival to the house's `door(box)` function. The door finds
16
- the relation by its heir, and the heir names one being and one of her
17
- occupants. An occupant is a being's name for the door's end of a relation.
18
- Asks to one being run one at a time, in the order they arrive. An ask
19
- marked `readOnly`, and the empty ask, run beside them. Asks to two beings
20
- run side by side.
21
-
22
- **Question 2.** The ground that runs the house holds its seed, sealed in
23
- the ground's drawer under the one key the ground holds outside itself. A
24
- keys body gives signatures and agreements from the seed, and never the
25
- seed itself. `House.open`
26
- hands the ground a hand, `ask({ id, method, args })`, which asks the being
27
- `id`, or the steward where none is named, as the occupant `root`. The
28
- steward places and removes every other being. Every other being holds the
29
- standing `steward`, which she cannot drop. The steward cannot dismiss
30
- `root`. So no path inside a house removes the edge back to what made it.
31
- `root` never arrives through a door. The ground serves the hands of all
32
- its houses in one place. On Node, that is a local socket only the
33
- ground's user may open.
34
-
35
- **Question 3.** The public being answers the zero head, where the ground's
36
- classes name one. A house with no public being answers every ask on the
37
- zero head with silence, as case 4. The public being reads each such asker
38
- as the occupant `stranger`, with the key its ask was signed by. A stranger
39
- reaches only her asks that are safe to repeat. The house keeps each
40
- zero-head choice by the box's signature for ten minutes. The same sealed
41
- bytes arriving again within that window hear the same choice, and nothing
42
- runs twice. That cache lives in the process, so a restart empties it.
43
-
44
- **Question 4.** The door opens any number of boxes at once, and judges
45
- one at a time on each relation. A box whose relation has another box in
46
- flight waits for it, and is judged again on the record it left. A box
47
- opened on a record that moved meanwhile is judged again too. So each box
48
- is admitted by what holds when the door chooses, and the highest number
49
- honoured never goes down. An admitted ask waits its turn among its
50
- being's asks, and its move lands in the ask's own write.
51
-
52
- **Question 5.** nervur calls what stands behind a door a house, and what
53
- it holds beings. The door's end of a relation is an occupant, named by an
54
- id its being chooses. The asking end keeps Quo's name, a standing. A
55
- standing that arrives by invitation is named `standing:` and sixteen hex
56
- digits drawn from its heir, so the same invitation taken again gives the
57
- same standing. The ids `root`, `stranger` and `steward` are reserved, with every
58
- id beginning `handle:` or `being:`. The process that opens a house is its
59
- ground. None of these names crosses a door.
60
-
61
- ## What a kit keeps
62
-
63
- **Question 6.** A ward's seed is sixty-four lowercase hex digits, and
64
- anything else opens no house. `SeedKeys` takes it as a string. A ground
65
- draws a fresh seed when a house is first added, and keeps it sealed in
66
- its drawer. The drawer's key rests outside the ground, in a file only
67
- its owner may read, the macOS keychain, a Worker's secret, or the
68
- platform's keystore. The house never holds the seed, and asks its keys
69
- body for operations alone. The lock is
70
- derived, not drawn. It is the ML-KEM-768 key pair from 64 bytes of
71
- HKDF-SHA-256 over the seed, under the label `nervur-lock`. It is made on
72
- first use and is the same every time. So a ward holds one lock, and its
73
- seed alone restores it whole. The ward keeps no heir's secret after it
74
- gives the invitation.
75
-
76
- **Question 7.** Every drawn byte comes from `crypto.getRandomValues`, the
77
- platform's Web Crypto source. The default crypto body, `NobleCrypto`, draws
78
- there for heir secrets, ephemeral secrets, announced keys and ids. Its
79
- ML-KEM encapsulation, from the noble library, draws from the same source.
80
- The lock draws nothing, since it derives from the seed. A ground may hand
81
- its own crypto body, and then the source is that body's.
82
-
83
- **Question 8.** For each heir, the door keeps whether it is spent, the key
84
- it holds, the key it vouches for, and the open and offered edge keys. It
85
- keeps the highest number it honoured as well. That record sits in the
86
- place of the being the heir reaches, beside her other relations. The house
87
- keeps it in the memory its ground hands it, sealed under a key derived
88
- from the seed. `FileMemory` and `LedgerMemory` write to disk, and the
89
- record survives a restart with them. A standing's record is kept the same
90
- way. Its number and its knock are written before a box leaves.
91
-
92
- **Question 9.** A door stops holding an heir when its being dismisses the
93
- occupant the heir reaches. It stops when a handle made for one use has its
94
- first ask land. It stops when the steward removes the being. An invitation
95
- taken by a standing of the same house binds inside the house, and its heir
96
- leaves the door then. An heir minted with a time to be spent in, and
97
- still unspent past it, is one the door never held. The door lets it go
98
- at the next mint or binding knock. A spent heir never expires, nor one
99
- minted without a time.
100
-
101
- **Question 10.** The door keeps no keys at removal, for any time.
102
- Dismissal deletes the heir from the door's index. So an ask signed by any
103
- of the relation's keys hears silence at once, and the door never answers
104
- `removed` in this version.
105
-
106
- **Question 11.** None. A door honours no number below the highest it
107
- honoured on a relation, and a number at or below it hears `repeated`. A
108
- nervur standing numbers each ask above every number it sent. So a retry
109
- never meets `repeated` for a box that arrived.
110
-
111
- ## What a kit answers
112
-
113
- **Question 12.** The door answers every box it refuses with silence or
114
- with one of Quo's words. It answers every admitted ask with a choice. The
115
- choice is the being's object, or silence where the being is absent or does
116
- not hold that asker. The door gives nothing where the memory refuses the
117
- write that holds the ask's move. Over TCP, the listener also answers
118
- nothing for a ward it does not hold, and for a door that fails with an
119
- error.
120
-
121
- **Question 13.** `seen` is sixteen lowercase hex digits. They are the first
122
- eight bytes of the SHA-256 of the canonical JSON of the describe that asker
123
- would hear. So `seen` changes exactly when that describe changes: the
124
- being's state, the asks shown to that asker, or their entries. Every
125
- object carries it, an answer and a describe alike, a refusal of `args`
126
- that repeat a key among them.
127
-
128
- **Question 14.** The empty ask answers a describe to any asker the door
129
- admits, a stranger on the zero head among them. A being that is absent
130
- answers silence instead. A describe holds the being's current state and
131
- every entry shown to the roles its asker holds, in every state. So two
132
- askers with different roles hear two describes. Its `lang` is
133
- `org.nervur.asks/1`, nervur's language above Quo, whose shapes are below.
134
- An entry's `description` is the class author's text. Its `args` and
135
- `result` are JSON Schema 2020-12, in a closed subset. A named ask that no
136
- entry shown to that asker names hears `{"error":{"message":"no such ask"}}`.
137
-
138
- ```text
139
- describe = { lang: "org.nervur.asks/1", kind?, description?, view?, state, asks }
140
- entry = { method, in, to, description?, args, result?, hints, wait }
141
- answer = { result } | { error: { message } }
142
- ```
143
-
144
- A stranger's describe names no `kind` and no `description`. A `view` is
145
- the being's markup as text, which a screen renders, and every asker is
146
- shown it.
147
-
148
- **Question 15.** A reply text holds no whitespace between tokens. An
149
- object reply writes `object` first and `seen` second. Its object is
150
- canonical JSON, with every object's keys sorted by UTF-16 code units. A
151
- word is written `{"quo":"removed"}`, and silence `{"silence":true}`.
152
-
153
- **Question 16.** No. nervur seals every payload and every reply text with
154
- no padding. It reads padding wherever padding arrives.
155
-
156
- **Question 17.** No. Each refusal returns as soon as its case is found.
157
- So a box refused at its head returns sooner than one refused at its
158
- signature.
159
-
160
- **Question 18.** The Quo layer names the case that refused each arrival,
161
- and the house discards it. Nothing in this version logs a refusal, or a
162
- reply that breaks a rule. A standing reads a reply that breaks a rule as
163
- silence, and keeps no record of why.
164
-
165
- ## What a kit asks
166
-
167
- **Question 19.** An invitation leaves a house as a handle. A being puts a
168
- handle in her answer, or in the `args` of a call outward. The house writes
169
- it as the hex of the invitation's canonical JSON. From there it travels
170
- however its receiver carries it. The minting house keeps no copy. It keeps
171
- the heir's public key and the record of the relation, never the heir's
172
- secret.
173
-
174
- **Question 20.** A standing whose knock surely reached no door sends the
175
- knock again, as the same bytes, until it may have. Its carry says so: no
176
- address took the box. A standing whose knock may have been heard, and
177
- brought no object back, recovers it in turns. Its next send is an ask
178
- with a new number, under the key its knock announced and the knock's edge
179
- key. The send after that is the knock again, as the same bytes. The two
180
- take turns until an object comes back, or a word to an ask. An awaited
181
- call makes one send within its wait, and the next call on the relation
182
- takes the next turn. An effect is sent again after a wait that starts at
183
- one second and doubles, never past five minutes. It stops at its
184
- deadline, which is seven days for a standing.
185
-
186
- **Question 21.** Over TCP and the web, a dialer waits thirty seconds for
187
- each address, unless the ground sets `wait` on its carry. An awaited call
188
- waits as long as the method it calls names. That is thirty seconds by
189
- default, never past five minutes, and never past the ground's `wait` on
190
- the house. It never waits past what is left of the ask that makes it. An
191
- awaited call to a far ward carries that time in the payload field
192
- `within`, in milliseconds. The ask it starts waits that long at most, and
193
- an ask whose time is spent runs nothing and hears silence. A being waits
194
- on no effect, and an effect's answer returns to her as an ask.
195
-
196
- **Question 22.** A standing numbers its asks from 1, each one above the
197
- last it sent. Every ask announces a fresh random key in `next`. The house
198
- sends one ask at a time on each relation, and the next waits for the reply
199
- to the last. The number and any knock are written before a box leaves.
200
- The standing moves only on an object answering an ask above every ask it
201
- has moved on. It then signs with the key that ask announced, and keeps no
202
- key it moved from. After a move, an ask that meets silence moves nothing.
203
- The next ask signs with the same key under the same edge key, with a new
204
- number and a new announced key.
205
-
206
- **Question 23.** The Quo layer reads a reply as one of four: an object
207
- with its `seen`, silence, one of Quo's three words, or nothing. The house
208
- treats silence, a word and nothing alike, as transient, and names no
209
- cause for any of them. An address that never answered, a spent heir and
210
- a reply that came late read the same. An awaited call fails with the
211
- method's name followed by `answered nothing`. An effect is sent again.
212
- Past its deadline, its reply ask reads `the call gave up at its
213
- deadline`. A being never reads silence, a word or nothing as such.
214
-
215
- ## What a kit carries
216
-
217
- **Question 24.** nervur stands Quo over TCP, as a listener and as a
218
- dialer, in `TcpCarry` from `nervur/node`. It carries plain TCP, with no TLS
219
- and no check beyond Quo's own. The listener binds `0.0.0.0` by default, on
220
- the port the ground names or one the system picks. One listener answers
221
- for every ward whose house listens on it, routed by the ward each ask
222
- names.
223
-
224
- nervur stands Quo over the web in `WebCarry`, both its post and its held
225
- line, as a listener and as a dialer. The listener is a handler on the
226
- ground's own HTTP listener, at the path `/quo` unless the ground names
227
- another. It answers a reply with status 200 and nothing with 204. It
228
- answers a request that is not a `POST` with 405, a body of the wrong size
229
- with 400, and a ward pk it holds no door for with 404. It answers the
230
- CORS protocol only for the origins its ground names, and no origin
231
- otherwise. A held line that does not offer the subprotocol `quo` is
232
- refused at its handshake with 400. TLS is the ground's listener's, and
233
- this carry adds none.
234
-
235
- **Question 25.** A standing learns where a ward is reached from the `at` of
236
- its invitation, and from which address answered. A house writes `at` in
237
- every invitation it mints. It writes the addresses the ground hands its
238
- carry, the same toward every holder. A carry that joins several lists
239
- every one's addresses. Where the ground hands none, `TcpCarry` writes the
240
- listener's own address, with `0.0.0.0` written as `127.0.0.1`.
241
-
242
- A carry keeps the door of every ward it listens for. A box to one of those
243
- wards goes to its door in the same process, before any address, and no
244
- connection is made. So the houses of one ground reach each other by the
245
- carry they share, whatever their invitations' `at` holds.
246
-
247
- A standing keeps its route: the address that last answered with an
248
- object or a word, which only a reply that opened as the ward's carries.
249
- Silence pins nothing. Each ask tries the route first, then the addresses
250
- of `at` in their order, one after another. The route is kept with the
251
- standing's record and survives a restart.
252
-
253
- A door writes `at` in an object reply when the ground's addresses differ
254
- from the ones that holder last heard, in its invitation or in a reply.
255
- It writes them once, and a later reply carries none until they change
256
- again. A reply lost after it carried them leaves that holder with the
257
- old addresses until the next change. A standing takes `at` from an
258
- object reply alone. It replaces the addresses it held, and a later reply
259
- with none leaves them as they stand. The dialer skips an
260
- address its carry does not speak. It looks a name up and takes its first
261
- address. One connection to each address carries many asks at once.
262
-
263
- The dialer refuses a loopback, private, link-local, shared or unspecified
264
- address, unless the ground sets `allowPrivate`. Over the web it reads
265
- the host as the URL writes it, and refuses `localhost` too. It moves to
266
- the next address after a refused address, a failed connection, a
267
- nothing frame, or a post answered with any status but 200 and a body. It
268
- carries the box no further after a wait that runs out, a connection that
269
- closes with the ask in flight, or a post that failed after it was sent.
270
- That ask may have been heard, and the send answers nothing.
271
-
272
- ## What is not the kit's either
273
-
274
- **Question 26.** `method` names an entry of the being's describe, and
275
- `args` are that entry's arguments. The house holds `args` to the entry's
276
- schema before the method runs, and answers a mismatch as an error. The
277
- `lang` `org.nervur.asks/1` names nervur's language, whose shapes Question
278
- 14 gives. A field `call` beside `method` carries a call id, and a field
279
- `within` the milliseconds its chain has left, as Question 21 gives. An ask whose
280
- call id that occupant already used hears the stored answer, and runs
281
- nothing. A call id is kept seven days.
282
-
283
- ## What a kit reads
284
-
285
- **Question 27.** nervur's JSON reader is iterative. It reads any nesting
286
- depth that a box of at most 1 MiB holds, and sets no length below that
287
- size. It takes lone surrogates written as escapes, and noncharacters, as
288
- they stand. Repeated keys anywhere inside `args` are answered
289
- `{"error":{"message":"the args repeat a key"}}`, and the method never runs.
290
- Numbers are read as IEEE 754 doubles. So an integer beyond 2^53 loses
291
- precision before the schema holds it. Fields of the payload that the spec
292
- does not name, `call` and `within` apart, are ignored. Inside a reply's
293
- `object`, a standing takes a repeated key and keeps its last value.
294
-
295
- ## What a kit shows
296
-
297
- **Question 28.** nervur reads a domain's vouch for every standing on a
298
- far ward. The domains it checks are the hosts of the invitation's
299
- `https` and `wss` addresses, so a domain that serves no web is never
300
- asked. It reads the file once the ask that takes the invitation lands, and
301
- again when the ward names new addresses in a reply. A being sees the
302
- domains that vouched beside each standing she holds, and shows them to
303
- the person as her class chooses. A domain that lists the ward is shown,
304
- and one that does not is not.