nervur 0.22.2-7 → 0.23.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.
package/FACULTIES.md CHANGED
@@ -15,14 +15,22 @@ the package's own tests run.
15
15
  ## What a faculty owes
16
16
 
17
17
  A faculty answers a blueprint: a name, and methods with their schemas.
18
- A maker in a registry makes it, and the ground hands it to its houses as
18
+ A registry holds it by name as `{ takes?, up, install? }`. The ground
19
+ raises it by its `up` into a body, and hands the body to its houses as
19
20
  an offer, with the kinds its entry grants.
20
21
 
21
22
  ```text
22
- faculty = { blueprint?, object?, window?, handler?, stop?, registry? }
23
+ faculty = { takes?, install?, up }
24
+ takes = { args?: schema, secrets?: { [name]: what it holds } }
25
+ body = { blueprint?, object?, window?, handler?, registry?, down? }
23
26
  offer = { blueprint, object, kinds?, window? }
24
27
  ```
25
28
 
29
+ - **It declares what it takes.** `takes.args` is a schema built with
30
+ `s` from `nervur/being`, which its entry's args meet. `takes.secrets`
31
+ names each secret its entry must name, with a line saying what it
32
+ holds. The hand refuses an entry that fails either, before it lands,
33
+ and `facultiesCatalog` shows it to whoever writes the entry.
26
34
  - **The object has the blueprint's methods.** Each takes one args object
27
35
  and a context, and answers `{ result }` or `{ error: { message } }`.
28
36
  - **An error is final, and a throw is not.** An error reaches the being
@@ -45,7 +53,7 @@ answered, with the same call id every time.
45
53
  So one call arrives more than once. A reply lost on its way back brings
46
54
  it again, and so does a program that died before it answered. A faculty
47
55
  that changes the world keeps each call id with the answer it gave, in
48
- the memory its maker receives, where a restart and a move keep it. It
56
+ the memory its `up` receives, where a restart and a move keep it. It
49
57
  answers a call id it has seen with that answer, and acts once.
50
58
 
51
59
  It keeps them for its `window`, seven days where the offer names none.
@@ -84,31 +92,43 @@ reaches her through a standing, so policy is written as a being.
84
92
 
85
93
  ### It lives in the ground
86
94
 
87
- The object arrives living. The ground stands each faculty its entries
88
- name, awaiting its maker, and the house never starts, stops or restarts
89
- it. Every being whose need it covers holds the same object. A maker
90
- receives three things beside the faculty's name.
95
+ The object arrives living. The ground raises each faculty its entries
96
+ name, awaiting its `up`, and the house never starts, stops or restarts
97
+ it. Every being whose need it covers holds the same object. Its `up`
98
+ receives four things beside the faculty's name.
91
99
 
92
100
  - **`args`** are its entry's, as the owner wrote them.
93
101
  - **`secrets`** are the secrets its entry names, set through the hand
94
- and kept sealed in the ground's drawer. No other code reads them.
102
+ and kept sealed in a being of the ground's dock. No other code reads
103
+ them.
95
104
  - **`memory`** is the faculty's own, a view of the ground's memory
96
105
  sealed under a key the ground derives for it. Its call ids live there,
97
106
  so they move with the ground.
107
+ - **`faculties`** holds the object of each body its entry names in
108
+ `faculties`, so one body calls another directly. It goes up after
109
+ each of them.
98
110
 
99
- A faculty answers four things beside its methods, each where it has
100
- one.
111
+ `install` receives the same, and does the slow work once for each entry.
112
+ A program's packages and a repository's checkout are installed there, so
113
+ going up again installs nothing.
114
+
115
+ A body answers four things beside its methods, each where it has one.
101
116
 
102
117
  - **`handler`** answers HTTP on the ground's one listener. It takes a
103
118
  `Request` and answers a `Response`, or `null` where the request is not
104
- its own. A site, an API or an MCP server is a faculty with a handler.
105
- - **`stop`** is called when the ground stops, faculties in the reverse
106
- of the order they stood.
107
- - **`registry`** makes more faculties and bodies, for every entry that
108
- names this faculty in `from`. A module of code, a git repository and a
109
- program's catalogue are each a registry.
119
+ its own. A site, an API or an MCP server is a body with a handler.
120
+ - **`down`** lets go of what its `up` opened. The ground calls it when
121
+ the body is updated, restarted or removed, and when the ground stops,
122
+ bodies in the reverse of the order they stood.
123
+ - **`registry`** holds more faculties, for every entry that names this
124
+ body in `from`. A module of code, a git repository and a program's
125
+ catalogue are each a registry.
110
126
  - **`window`** is how long it remembers a call id.
111
127
 
128
+ The hand changes a body. `faculties update` lands a new entry, and the
129
+ body goes down and up on it. `faculties restart` takes it down and up on
130
+ the same entry. Each house that names it opens again.
131
+
112
132
  ## Three ways to wrap a program
113
133
 
114
134
  | Way | What the object is | What a crash takes |
@@ -120,7 +140,7 @@ one.
120
140
  ## The bridge
121
141
 
122
142
  `bridge({ command, args, env, cwd, memory })` from `nervur/node` starts
123
- a program and answers a faculty. A NodeGround makes one by the maker
143
+ a program and answers a body. A NodeGround raises one by its faculty
124
144
  `bridge`, from its entry alone. The program may be written in any
125
145
  language. It speaks one JSON value a line on its standard streams.
126
146
 
@@ -143,7 +163,7 @@ in { id, result } | { id, error } the ground's answer to that
143
163
  the same every time that call is sent, in every life of the program.
144
164
  A handle called with no `call` is refused.
145
165
  - **It starts with an empty environment.** It holds only what `env`
146
- names, so it never reads the ground's key. The maker `bridge` names
166
+ names, so it never reads the ground's key. The faculty `bridge` names
147
167
  there the secrets of its entry, each under its name.
148
168
  - **It keeps its state in the faculty's memory.** A memory line names
149
169
  `read`, `list` or `write` and the memory's args, every entry's bytes
@@ -365,22 +385,22 @@ it later, once.
365
385
 
366
386
  The Pi's folder holds the program and a folder of classes for its
367
387
  house, and no code of the ground's. The relay stands from its entry,
368
- made by the NodeGround's own maker `bridge`, and granted to the twin's
369
- class alone.
388
+ raised by the faculty `bridge` of the NodeGround's folder, and granted
389
+ to the twin's class alone.
370
390
 
371
391
  ```bash
372
- npx nervur faculties add name=relay make=bridge args='{"command":"python3","args":["relay.py"]}' kinds='["org.example.garage"]'
392
+ npx nervur faculties add name=relay from=folder make=bridge args='{"command":"python3","args":["relay.py"]}' kinds='["org.example.garage"]'
373
393
  ```
374
394
 
375
395
  The house is added once, and names the relay among the faculties it
376
396
  receives.
377
397
 
378
398
  ```bash
379
- npx nervur houses add name=garage classes='{"body":"folder","at":"classes"}' faculties='["relay"]'
399
+ npx nervur houses add name=garage classes='{"faculty":"folder","at":"classes"}' faculties='["relay"]'
380
400
  ```
381
401
 
382
- Both entries rest sealed in the ground's drawer, so the ground stands
383
- the relay again at every start.
402
+ Both entries rest sealed as cells of the ground's dock, so the ground
403
+ stands the relay again at every start.
384
404
 
385
405
  ## In JavaScript
386
406
 
@@ -423,16 +443,16 @@ serve(Doorbell, {
423
443
  });
424
444
  ```
425
445
 
426
- Its entry makes it with the maker `bridge`, its command `node` and its
427
- args `["doorbell.js"]`. A faculty that needs no process of its own is a
428
- plain object a registry's maker answers instead, as the shop's payments
446
+ Its entry raises it with the faculty `bridge`, its command `node` and
447
+ its args `["doorbell.js"]`. A faculty that needs no process of its own
448
+ is a plain object its `up` answers instead, as the shop's payments
429
449
  are in [Writing for nervur](AUTHORING.md).
430
450
 
431
451
  ## Testing a faculty
432
452
 
433
453
  A faculty is tested on BenchGround, the ground in memory from
434
454
  `nervur/bench`, with the program itself behind the bridge. The test
435
- hands the bench a registry whose maker bridges the program, as a
455
+ hands the bench a registry whose `bridge` faculty bridges the program, as a
436
456
  NodeGround's own does, and stands the relay through the ground's hand,
437
457
  as an owner does. A `FakeNetwork` joins
438
458
  grounds and loses what the test tells it to lose, and its one clock
@@ -476,11 +496,11 @@ test('Each tap on the phone pulses the relay once, whatever fails between', { ti
476
496
  host: 'pi',
477
497
  names: ['garage.local'],
478
498
  modules: { pi },
479
- registry: { faculties: { bridge: ({ memory }) => bridge({ command: 'python3', args: [relay], cwd: pin, memory }) } },
499
+ registry: { faculties: { bridge: { up: ({ memory }) => bridge({ command: 'python3', args: [relay], cwd: pin, memory }) } } },
480
500
  });
481
501
  t.after(() => garage.down());
482
502
  // The relay, granted to the twin's class alone.
483
- await garage.hand({ faculty: 'faculties', method: 'add', args: { name: 'relay', make: 'bridge', kinds: ['org.example.garage'] } });
503
+ await garage.hand({ method: 'facultiesAdd', args: { name: 'relay', make: 'bridge', kinds: ['org.example.garage'] } });
484
504
  await garage.add('garage', 'pi', { faculties: ['relay'] });
485
505
  await garage.ask({ house: 'garage', method: 'bear', args: { kind: 'org.example.garage', id: 'door' } });
486
506
 
package/GROUNDS.md CHANGED
@@ -14,47 +14,95 @@ kept by what the ground stands on: a file, a keychain, a Worker's
14
14
  secret. The part of a ground that answers it is its unlock. Everything
15
15
  else the ground keeps is sealed under that key.
16
16
 
17
- **It keeps its drawer in its one memory.** The drawer is the ground's
18
- own sealed places. It holds each house's entry and seed, each faculty's
19
- entry, every secret you set, and each house's ward. A memory that holds
20
- places the key does not open is refused, so a ground never opens on
21
- another's memory.
22
-
23
- **Its houses keep their places in the same memory.** Each house and each
24
- faculty sees a view of the ground's memory under a prefix of its own. A
25
- house seals its own rows, and the ground seals each faculty's. So what
26
- rests on the disk is ciphertext, and copying the key, the memory and the
27
- code moves the whole ground.
28
-
29
- **It stands its faculties on a ladder.** A registry is code that makes
30
- faculties and bodies by name. The ground's own registry is its
31
- terrain's. A faculty may carry a registry of its own, and the faculties
32
- an entry makes `from` it stand after it. A faculty that fails to stand
33
- stays down and says why, and the ground boots beside it.
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.
34
63
 
35
64
  ```text
36
- recipe { make: 'module', args: { at: 'recipe.ts' } }
65
+ recipe { from: 'folder', make: 'module', args: { at: 'recipe.ts' } }
37
66
  payments { from: 'recipe', make: 'payments', secrets: ['stripe-key'], kinds: ['com.acme.order'] }
38
67
  ```
39
68
 
40
- **It opens each house on its entry.** An entry names the body of the
41
- house's code, the custom faculties it may use, and the longest any of
42
- its asks may run. It names a body of memory only where the house keeps
43
- its places apart from the ground's memory.
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.
44
74
 
45
75
  ```text
46
- shop { classes: { body: 'folder', at: 'shop' }, faculties: ['payments'], wait: 60000 }
76
+ shop { classes: { faculty: 'folder', at: 'shop' }, faculties: ['payments'], wait: 60000 }
47
77
  ```
48
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
+
49
89
  **It grants a faculty in two steps.** A house uses only the faculties its
50
90
  entry names. Inside it, a being holds one only where the faculty's entry
51
- names her class in `kinds`, or where it names none. So a raw shell
91
+ names her class in `kinds`, or where it names none. So a raw program
52
92
  reaches one house and one class inside it.
53
93
 
54
- **It hands each maker its secrets.** A secret is set through the hand
55
- and kept in the drawer. A faculty's entry names the secrets its maker
56
- receives, and no other code reads one. The hand lists their names, and
57
- never a value.
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.
58
106
 
59
107
  **It hooks every door and runs one listener.** Each house's door goes to
60
108
  the ground's carry, which also delivers between the ground's own houses
@@ -62,36 +110,64 @@ without touching the network. Everything that speaks HTTP, Quo over the
62
110
  web and every face, is a handler on one listener. A faculty stood while
63
111
  the ground runs is served at once.
64
112
 
65
- **It serves its owner's hand.** The hand answers three things: what the
66
- ground holds, a faculty's method, and an ask of any being of any house,
67
- as the house's owner. Four faculties are the ground's own.
68
-
69
- | Faculty | Its methods | Who reaches it |
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 |
70
133
  | --- | --- | --- |
71
- | `houses` | `add`, `remove`, `list` | the hand, and the kinds its entry grants |
72
- | `faculties` | `add`, `remove`, `list` | the hand, and the kinds its entry grants |
73
- | `secrets` | `set`, `remove`, `list` | the hand alone |
74
- | `moves` | `out`, `in` | the hand alone |
75
-
76
- **It lets a pilot possess it from afar.** An entry for `houses` or
77
- `faculties` holds `kinds` alone, and grants it to one pilot being. A
78
- standing on that being then pilots the ground. `secrets` and `moves`
79
- take no entry, so no being ever holds a seed or a secret.
80
-
81
- **It moves a house by its seed and its memory.** `moves` takes a house
82
- out as its seed and every place of its memory, and another ground takes
83
- them in. The house keeps its identity, so every relation still answers
84
- and no far house notices.
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.
85
161
 
86
162
  ## The five grounds
87
163
 
88
- | Ground | Where it runs | When it wakes | Its unlock | Its memory |
89
- | --- | --- | --- | --- | --- |
90
- | NodeGround | a server, a desktop, a Pi | always on | a key file, or the macOS keychain | a ledger in its folder |
91
- | EdgeGround | a Cloudflare Worker and its Durable Object | per request, per message, per alarm | the Worker's secret | the object's storage |
92
- | 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 |
93
- | AppGround | an iOS or Android app's web view | per launch, and by push | the Keychain or the Keystore | the app's native store |
94
- | BenchGround | memory, in a test | as the test moves its clock | a key drawn from the bench's seed | memory in the process |
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 |
95
171
 
96
172
  The same class runs unchanged on every row. What differs is the bodies
97
173
  each ground hands its houses.
@@ -108,11 +184,30 @@ shows. The ground's folder is an ES module package, so its
108
184
  port is set, on the web. [The command](COMMAND.md) lists its settings
109
185
  and runs its hand.
110
186
 
111
- **Its registry makes three things.** The body `folder` loads a house's
112
- classes from a folder inside it. The maker `module` imports a module
113
- inside it as a registry, whose `faculties`, `memory` and `classes` are
114
- maps of makers. The maker `bridge` starts a program, in any language,
115
- and hands it the secrets its entry names as its environment.
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`.
116
211
 
117
212
  **Its key rests in `state/key`, its owner's alone.** A key file others
118
213
  may read is refused, as ssh refuses a key. On macOS,
@@ -120,10 +215,17 @@ may read is refused, as ssh refuses a key. On macOS,
120
215
  instead. Keep `state/` as you keep an ssh key: whoever holds the key and
121
216
  the ledger holds the ground.
122
217
 
123
- **It keeps its memory as a ledger.** Every write is one line, chained to
124
- the line before it and synced before it counts. A ledger edited anywhere
125
- but its end is refused. A witness file kept on another disk refuses a
126
- restored copy that is behind.
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.
127
229
 
128
230
  **It runs a program as a faculty, in any language.** The bridge starts a
129
231
  program and speaks one JSON value a line on its standard streams. The
@@ -151,24 +253,24 @@ export default EdgeGround.worker();
151
253
  ```
152
254
 
153
255
  The Worker binds the object's class as `GROUND`, with SQLite storage.
154
- `registry` joins the terrain's own, so an entry makes `payments` with no
155
- `from`. A house's entry names its code with `classes: { body: 'bundle',
156
- at: 'shop' }`.
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' }`.
157
259
 
158
- **Its settings are the Worker's.**
260
+ **Its Worker holds two secrets and nothing else.**
159
261
 
160
- | Setting | What it sets |
262
+ | Variable | What it names |
161
263
  | --- | --- |
162
264
  | `NERVUR_SECRET` | the ground's key, sixty-four hex digits; set as a secret |
163
265
  | `NERVUR_HAND` | the key its hand answers; set as a secret |
164
- | `NERVUR_ADDRESSES` | the addresses it is reached at, by commas, the held line first |
165
- | `NERVUR_ORIGINS` | the page origins it answers |
166
- | `NERVUR_ALLOW_PRIVATE` | `1` to let it dial a private address |
167
- | `NERVUR_WAIT` | the longest any ask may run, a minute where unset |
168
266
 
169
267
  A Worker learns no name it is reached by, so it writes only the
170
- addresses `NERVUR_ADDRESSES` names. Its faculties take their secrets
171
- from its drawer, as on every ground.
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.
172
274
 
173
275
  **Its hand answers its key alone.** The hand is `POST /nervur/hand`, with
174
276
  the key as a bearer token and one request as the body. Every other
@@ -190,18 +292,19 @@ the object. A watch held on that line answers the moment the change lands.
190
292
 
191
293
  **A BrowserGround is one ground for its origin.** Every tab and the
192
294
  service worker of an origin share it. The tab holding a Web Lock runs
193
- the ground, and every other tab reaches its hand. It only dials, so it
194
- answers no face. Whoever serves the origin's script possesses the
195
- ground, so its origin serves nothing else.
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.
196
298
  [The package's start](README.md) opens one in a page.
197
299
 
198
300
  **Its registry is the one the page hands.** `BrowserGround.open({
199
- registry })` joins it to the terrain's own, whose body `origin` loads a
200
- house's classes from the origin.
301
+ registry })` joins it to the terrain's own, whose faculty `origin`
302
+ serves each house its classes from the origin.
201
303
 
202
- **An AppGround is a BrowserGround with the shell's bodies.** The shell
203
- hands in two small interfaces, one for secrets and one for a store, and
204
- the library holds the rest. The ground's key rests in the secret store.
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.
205
308
 
206
309
  ## BenchGround
207
310
 
package/README.md CHANGED
@@ -96,11 +96,11 @@ Run the ground in the folder, and leave it running.
96
96
  npx nervur up .
97
97
  ```
98
98
 
99
- In a second shell, add the house once. The ground keeps its entry in its
100
- sealed drawer, and opens it again at every start.
99
+ In a second shell, add the house once. The ground keeps its entry as a
100
+ sealed cell of its dock, and opens it again at every start.
101
101
 
102
102
  ```bash
103
- npx nervur houses add name=main classes='{"body":"folder","at":"house"}'
103
+ npx nervur houses add name=main classes='{"faculty":"folder","at":"house"}'
104
104
  ```
105
105
 
106
106
  Then ask the steward through the ground's hand.
@@ -130,9 +130,8 @@ const ground = await BrowserGround.open();
130
130
 
131
131
  // The house's code is a module on this origin, and its rows rest sealed in IndexedDB.
132
132
  await ground.hand({
133
- faculty: 'houses',
134
- method: 'add',
135
- args: { name: 'main', classes: { body: 'origin', at: '/house/index.js' } },
133
+ method: 'housesAdd',
134
+ args: { name: 'main', classes: { faculty: 'origin', at: '/house/index.js' } },
136
135
  });
137
136
 
138
137
  console.log(await ground.hand({ house: 'main', method: 'hello', args: { name: 'Ada' } }));
@@ -154,10 +153,11 @@ keeps. [Writing for nervur](AUTHORING.md) shows both.
154
153
  | Entry | For |
155
154
  | --- | --- |
156
155
  | `nervur/being` | writing a being: `Being`, `s`, `need`, `tableOf`, `Args`, `Result`, `Json`, `Table` |
157
- | `nervur` | any engine: `Ground`, `House` and the bodies they take |
156
+ | `nervur` | any engine: `Ground`, `House`, `DockPilot`, `vouchesOf` and the bodies they take |
158
157
  | `nervur/node` | a ground on Node: `NodeGround`, the `nervur` command, and its bodies |
159
158
  | `nervur/browser` | a ground in a page or its service worker: `BrowserGround` and its bodies |
160
- | `nervur/app` | a ground in a phone's app: `AppGround`, and the two interfaces its shell fills |
159
+ | `nervur/edge` | a ground on the edge, a Worker and its Durable Object: `EdgeGround` and its bodies |
160
+ | `nervur/app` | a ground in a phone's app: `AppGround`, and the three interfaces its shell fills: `NativeShell`, `NativeSecrets` and `NativeStore` |
161
161
  | `nervur/serve` | a faculty's program in JavaScript: `serve` |
162
162
  | `nervur/bench` | tests: `Bench`, `BenchGround` and `FakeNetwork` |
163
163
 
@@ -1,11 +1,10 @@
1
- import { ClassList, Ground, type Faculty, type Registry } from '../index.ts';
1
+ import { ClassList, Ground, type Body, type Registry } from '../index.ts';
2
2
  import { FakeMemory } from './fake-memory.ts';
3
3
  import { type FakeNetwork } from './fake-network.ts';
4
4
  import { FakeUnlock } from './fake-unlock.ts';
5
5
  import { SeededCrypto } from './seeded.ts';
6
6
  type BeingClass = ConstructorParameters<typeof ClassList>[0]['steward'];
7
7
  type Entry = Parameters<Ground['add']>[1];
8
- type HandAsk = Parameters<Ground['ask']>[0];
9
8
  type Standing = Awaited<ReturnType<Ground['add']>>;
10
9
  /** A house module: what a folder's index exports. */
11
10
  export interface HouseModule {
@@ -13,8 +12,8 @@ export interface HouseModule {
13
12
  readonly public?: BeingClass;
14
13
  readonly beings?: readonly BeingClass[];
15
14
  }
16
- /** A faculty the test writes, living, with the kinds it is granted. */
17
- export type Living = Faculty & {
15
+ /** A body the test writes, living, with the kinds it is granted. */
16
+ export type Living = Body & {
18
17
  readonly kinds?: readonly string[];
19
18
  };
20
19
  /** What a ground keeps across its lives: its key, its randomness, its memory, and each house's own where it names the `fake` body. */
@@ -61,8 +60,9 @@ export declare class BenchGround {
61
60
  add(name: string, from?: string | Entry, rest?: Omit<Entry, 'classes'>): Promise<Standing>;
62
61
  remove(name: string): Promise<void>;
63
62
  list(): readonly Standing[];
64
- ask(request: HandAsk): ReturnType<Ground['ask']>;
65
- /** The ground's hand, as its owner holds it: `describe`, a faculty's method, or an ask of a being. */
63
+ /** A being in a house asked as `root`, the house's steward where no id is named. */
64
+ ask(request: Parameters<Ground['ask']>[0]): ReturnType<Ground['ask']>;
65
+ /** The ground's hand, as its owner holds it: `describe`, or an ask of a being in a house, or of the dock's steward where no house is named. */
66
66
  hand(request: Parameters<Ground['hand']>[0]): ReturnType<Ground['hand']>;
67
67
  /**
68
68
  * A request to the ground's one listener, with no socket: each faculty's