nervur 0.22.2-6 → 0.22.2-7
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/AUTHORING.md +74 -44
- package/COMMAND.md +25 -10
- package/FACES.md +20 -9
- package/FACULTIES.md +163 -92
- package/GROUNDS.md +120 -67
- package/KIT-SPEC.md +10 -7
- package/README.md +16 -14
- package/dist/app/app-ground.d.ts +1 -1
- package/dist/app/app-ground.js +5 -5
- package/dist/app/index.d.ts +1 -1
- package/dist/app/index.js +1 -1
- package/dist/app/native.d.ts +3 -3
- package/dist/app/native.js +3 -3
- package/dist/bench/bench-ground.d.ts +18 -14
- package/dist/bench/bench-ground.js +34 -33
- package/dist/bench/fake-unlock.d.ts +6 -0
- package/dist/bench/fake-unlock.js +10 -0
- package/dist/bodies/kept.d.ts +5 -16
- package/dist/bodies/kept.js +17 -36
- package/dist/browser/browser-ground.d.ts +8 -16
- package/dist/browser/browser-ground.js +11 -22
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/locked-unlock.d.ts +24 -0
- package/dist/browser/locked-unlock.js +85 -0
- package/dist/edge/edge-ground.d.ts +8 -17
- package/dist/edge/edge-ground.js +14 -26
- package/dist/edge/index.d.ts +2 -2
- package/dist/edge/index.js +1 -1
- package/dist/edge/secret-unlock.d.ts +7 -0
- package/dist/edge/secret-unlock.js +13 -0
- package/dist/ground/ground.d.ts +155 -103
- package/dist/ground/ground.js +548 -314
- package/dist/ground/views.d.ts +59 -0
- package/dist/ground/views.js +188 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/node/bridge.d.ts +3 -0
- package/dist/node/bridge.js +66 -5
- package/dist/node/cli.js +32 -19
- package/dist/node/index.d.ts +2 -4
- package/dist/node/index.js +1 -3
- package/dist/node/node-ground.d.ts +6 -16
- package/dist/node/node-ground.js +59 -53
- package/dist/node/unlock.d.ts +17 -0
- package/dist/node/unlock.js +86 -0
- package/dist/serve/index.d.ts +20 -7
- package/dist/serve/index.js +21 -9
- package/package.json +1 -1
- package/dist/bench/fake-custody.d.ts +0 -15
- package/dist/bench/fake-custody.js +0 -39
- package/dist/bench/fake-keys.d.ts +0 -4
- package/dist/bench/fake-keys.js +0 -9
- package/dist/browser/locked-custody.d.ts +0 -36
- package/dist/browser/locked-custody.js +0 -114
- package/dist/edge/secret-custody.d.ts +0 -6
- package/dist/edge/secret-custody.js +0 -40
- package/dist/node/custody.d.ts +0 -34
- package/dist/node/custody.js +0 -58
- package/dist/node/file-keys.d.ts +0 -11
- package/dist/node/file-keys.js +0 -44
- package/dist/node/held-keys.d.ts +0 -14
- package/dist/node/held-keys.js +0 -36
- package/dist/node/keychain-keys.d.ts +0 -12
- package/dist/node/keychain-keys.js +0 -55
package/AUTHORING.md
CHANGED
|
@@ -11,7 +11,7 @@ The shop has three classes and one faculty.
|
|
|
11
11
|
- `Order` is one order, from its first item to its shipping.
|
|
12
12
|
- `Shop` is the steward, the being that runs the house.
|
|
13
13
|
- `Lobby` is the public being, which strangers may ask.
|
|
14
|
-
- `Payments` is a faculty that charges money, which
|
|
14
|
+
- `Payments` is a faculty that charges money, which a maker in
|
|
15
15
|
`recipe.ts` makes.
|
|
16
16
|
|
|
17
17
|
## Words
|
|
@@ -31,7 +31,8 @@ The shop has three classes and one faculty.
|
|
|
31
31
|
| role | a named test over the asker and her cells |
|
|
32
32
|
| state | a name read from her cells that decides which asks exist |
|
|
33
33
|
| house | what holds beings, keeps their cells, and seals every ask |
|
|
34
|
-
| ground | the process houses run in, holding their seeds, faculties and
|
|
34
|
+
| ground | the process houses run in, holding one key and sealing their seeds, faculties and secrets under it |
|
|
35
|
+
| registry | code that makes faculties and bodies by name, for the ground to stand |
|
|
35
36
|
|
|
36
37
|
## A being
|
|
37
38
|
|
|
@@ -587,7 +588,8 @@ type Answer = { result: { pending: boolean } } | { error: { message: string } };
|
|
|
587
588
|
/**
|
|
588
589
|
* A payment provider in the ground's process. It answers a call id it has
|
|
589
590
|
* seen with the answer it gave, so an effect sent twice charges once. A
|
|
590
|
-
* provider that changes the world keeps these
|
|
591
|
+
* provider that changes the world keeps these in the memory its maker
|
|
592
|
+
* receives, where a restart and a move keep them.
|
|
591
593
|
*/
|
|
592
594
|
export class Payments {
|
|
593
595
|
readonly #answered = new Map<string, Answer>();
|
|
@@ -615,28 +617,31 @@ export class Payments {
|
|
|
615
617
|
export const paymentsOffer = (payments: Payments): Offer => ({ blueprint: PaymentsBlueprint, object: payments, window: 7 * 86_400_000 });
|
|
616
618
|
```
|
|
617
619
|
|
|
618
|
-
An offer is `{ blueprint, object, kinds?, window
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
faculty
|
|
620
|
+
An offer is `{ blueprint, object, kinds?, window? }`. The object answers
|
|
621
|
+
each call with its call id, and one that changes the world answers a
|
|
622
|
+
call id it has seen with the answer it gave. A registry holds a maker
|
|
623
|
+
for each faculty by name. The ground stands a faculty when an entry names
|
|
624
|
+
its maker, and the entry's `kinds` grants it to the classes it names.
|
|
625
|
+
[Writing a faculty](FACULTIES.md) teaches the craft whole, with a faculty
|
|
626
|
+
written in Python.
|
|
624
627
|
|
|
625
628
|
```ts
|
|
626
629
|
// recipe.ts
|
|
627
630
|
import { Payments, paymentsOffer } from './payments.ts';
|
|
628
631
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
+
// A registry: the ground makes each faculty an entry names, by its maker here.
|
|
633
|
+
export const faculties = {
|
|
634
|
+
payments: () => paymentsOffer(new Payments()),
|
|
635
|
+
};
|
|
632
636
|
```
|
|
633
637
|
|
|
634
638
|
## A ground
|
|
635
639
|
|
|
636
640
|
A ground is the process houses run in, and you write none. `nervur up`
|
|
637
|
-
runs one on a folder:
|
|
638
|
-
|
|
639
|
-
|
|
641
|
+
runs one on a folder of code: a folder for each house, and each module
|
|
642
|
+
your entries name. It holds one key in `state/`, and keeps every entry
|
|
643
|
+
sealed in its drawer: which faculties stand, and which houses open on
|
|
644
|
+
which bodies.
|
|
640
645
|
|
|
641
646
|
### The shop's folder
|
|
642
647
|
|
|
@@ -676,11 +681,14 @@ The ground boots in one order, and a stop is that order reversed, on an
|
|
|
676
681
|
interrupt and on `SIGTERM`.
|
|
677
682
|
|
|
678
683
|
1. **Lock.** One ground to its state.
|
|
679
|
-
2. **
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
+
2. **Key.** Its key is read from `state/key`, drawn there on the first
|
|
685
|
+
start.
|
|
686
|
+
3. **Drawer.** Its ledger opens, and the key opens its drawer.
|
|
687
|
+
4. **Ladder.** Each faculty its drawer names stands on its registry. One
|
|
688
|
+
that fails stays down, and says why.
|
|
689
|
+
5. **Houses.** Each house of the drawer opens on its bodies.
|
|
690
|
+
6. **Hook.** The listeners, then the hand on its socket.
|
|
691
|
+
7. **Ready.** It tells systemd it is up, where systemd waits.
|
|
684
692
|
|
|
685
693
|
It is set by its environment.
|
|
686
694
|
|
|
@@ -693,26 +701,45 @@ It is set by its environment.
|
|
|
693
701
|
| `NERVUR_ALLOW_PRIVATE` | `1` to dial private and loopback addresses, as two grounds on one machine do |
|
|
694
702
|
| `NERVUR_BIND` | the address it listens on, `0.0.0.0` where unset |
|
|
695
703
|
| `NERVUR_STATE` | its state, `state/` in its folder where unset |
|
|
696
|
-
| `
|
|
704
|
+
| `NERVUR_UNLOCK` | `keychain:<account>` keeps its key in the macOS keychain, in place of `state/key` |
|
|
697
705
|
| `NERVUR_WAIT` | its bound on every ask, in milliseconds |
|
|
698
706
|
|
|
699
|
-
The state holds
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
707
|
+
The state holds the key in a file its owner alone reads, and the
|
|
708
|
+
ground's ledger. Every house keeps its rows in that ledger, sealed. A
|
|
709
|
+
ledger appends every write and never rewrites one. Its witness keeps
|
|
710
|
+
where it last stood, and a ledger behind its witness is refused. So a
|
|
711
|
+
ledger restored alone cannot replay what a house already answered,
|
|
712
|
+
though a whole state folder restored with its witness is not seen. A
|
|
713
|
+
lost key is a lost ground.
|
|
714
|
+
|
|
715
|
+
The ladder stands once, and the ground stands it again at every start.
|
|
716
|
+
The first entry stands the folder's `recipe.ts` as a registry, by the
|
|
717
|
+
ground's own maker `module`. The second makes the payments from it.
|
|
718
|
+
|
|
719
|
+
```bash
|
|
720
|
+
npx nervur faculties add name=recipe make=module args='{"at":"recipe.ts"}'
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
```bash
|
|
724
|
+
npx nervur faculties add name=payments from=recipe make=payments
|
|
725
|
+
```
|
|
705
726
|
|
|
706
727
|
A house is added once, and the ground opens it again at every start.
|
|
707
728
|
|
|
708
729
|
```bash
|
|
709
|
-
npx nervur houses add name=shop
|
|
730
|
+
npx nervur houses add name=shop classes='{"body":"folder","at":"classes"}' faculties='["payments"]'
|
|
710
731
|
```
|
|
711
732
|
|
|
712
|
-
`
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
733
|
+
`classes` names the body of the house's code. `folder` is the ground's
|
|
734
|
+
own, and a registry may add more, a git repository among them. A house
|
|
735
|
+
keeps its rows in the ground's ledger unless its entry names a `memory`
|
|
736
|
+
body. `faculties` names what the house receives, and within it each
|
|
737
|
+
faculty's entry names in `kinds` the classes that hold it.
|
|
738
|
+
|
|
739
|
+
A secret reaches a faculty the same way, and never through the
|
|
740
|
+
environment. `npx nervur secrets set -` reads `{ name, value }` from
|
|
741
|
+
standard input into the ground's sealed drawer. A faculty's entry names
|
|
742
|
+
the secrets its maker receives in `secrets`.
|
|
716
743
|
|
|
717
744
|
### The hand
|
|
718
745
|
|
|
@@ -774,7 +801,7 @@ with `loginctl enable-linger`. On macOS, the agent goes to
|
|
|
774
801
|
|
|
775
802
|
### In a page
|
|
776
803
|
|
|
777
|
-
`BrowserGround.open({
|
|
804
|
+
`BrowserGround.open({ registry })` from `nervur/browser` runs the same
|
|
778
805
|
houses in a page. Every tab and the service worker of one origin share
|
|
779
806
|
one ground: the one holding the Web Lock runs it, and the others reach
|
|
780
807
|
its hand over a `BroadcastChannel`. When it closes, the next opens the
|
|
@@ -782,12 +809,12 @@ ground from the same storage. `hand` answers the same three requests
|
|
|
782
809
|
the command sends: `describe`, a faculty's method, and an ask of a being
|
|
783
810
|
in a named house.
|
|
784
811
|
|
|
785
|
-
Its bodies are the browser's.
|
|
786
|
-
IndexedDB holds unextractable, and memory is IndexedDB
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
812
|
+
Its bodies are the browser's. The ground's key is sealed under an AES
|
|
813
|
+
key that IndexedDB holds unextractable, and its memory is IndexedDB.
|
|
814
|
+
Classes load from the page's own origin through the `origin` body, `{
|
|
815
|
+
body: 'origin', at: '/house/index.js' }`, and a path off the origin is
|
|
816
|
+
refused. The registry is the object you pass: makers of faculties, and
|
|
817
|
+
of any custom body, beside the terrain's own.
|
|
791
818
|
|
|
792
819
|
Any script on the origin can use the ground's keys, so the ground is
|
|
793
820
|
whoever serves the origin's script. Give it an origin of its own, serve
|
|
@@ -811,10 +838,10 @@ app's web view, on two interfaces the shell fills in native code:
|
|
|
811
838
|
which lands every write only where each key in `expect` still holds
|
|
812
839
|
what it names, and answers whether it landed.
|
|
813
840
|
|
|
814
|
-
The library holds the rest.
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
841
|
+
The library holds the rest. The ground's key goes into the secret store,
|
|
842
|
+
and its memory into the native store, which the system never evicts as
|
|
843
|
+
it may a web view's storage. A push token reaches the ground through a
|
|
844
|
+
faculty your registry makes.
|
|
818
845
|
|
|
819
846
|
## What the house guarantees
|
|
820
847
|
|
|
@@ -871,5 +898,8 @@ at her call, or where an ask arrives.
|
|
|
871
898
|
- A send to a private address, unless its ground allows it.
|
|
872
899
|
- A call on the house beside `House.open`, `door` and `ask`.
|
|
873
900
|
- A faculty in a house's code. Faculties are the ground's.
|
|
874
|
-
- A
|
|
901
|
+
- A drawer opened with a key that did not seal it.
|
|
902
|
+
- A secret read by a being, a describe or anyone but a maker its entry
|
|
903
|
+
names.
|
|
904
|
+
- A faculty entry for `secrets` or `moves`, which the hand alone reaches.
|
|
875
905
|
- A ground an owner must write. Each terrain's ships.
|
package/COMMAND.md
CHANGED
|
@@ -7,17 +7,21 @@ have read [the package's start](README.md), which runs a first ground.
|
|
|
7
7
|
|
|
8
8
|
## Starting a ground
|
|
9
9
|
|
|
10
|
-
`nervur up` runs a NodeGround on a folder until it is stopped. The
|
|
11
|
-
holds
|
|
12
|
-
|
|
10
|
+
`nervur up` runs a NodeGround on a folder until it is stopped. The
|
|
11
|
+
folder holds your code: a folder for each house, and each module or
|
|
12
|
+
program your entries name. `state/` holds the ground's key, its ledger
|
|
13
|
+
and its hand. The key is drawn on the first start, into a file your user
|
|
14
|
+
alone reads.
|
|
13
15
|
|
|
14
16
|
```bash
|
|
15
17
|
npx nervur up .
|
|
16
18
|
```
|
|
17
19
|
|
|
18
20
|
The ground stops cleanly on an interrupt and on `SIGTERM`. It takes a
|
|
19
|
-
lock on its
|
|
20
|
-
start.
|
|
21
|
+
lock on its state, so a second `nervur up` on the same folder refuses to
|
|
22
|
+
start. Keep `state/` as you keep an ssh key: whoever holds its key and
|
|
23
|
+
its ledger holds the ground, and without the key the ledger opens
|
|
24
|
+
nothing.
|
|
21
25
|
|
|
22
26
|
`nervur service` prints what keeps the ground running across reboots: a
|
|
23
27
|
systemd unit on Linux, a launchd job on macOS. Nothing is installed; you
|
|
@@ -40,7 +44,7 @@ A ground reads its settings from the environment.
|
|
|
40
44
|
| `NERVUR_ADDRESSES` | the public addresses written into invitations, by commas |
|
|
41
45
|
| `NERVUR_ORIGINS` | the page origins the web listener answers, by commas |
|
|
42
46
|
| `NERVUR_ALLOW_PRIVATE` | `1` to let the ground dial a private or loopback address |
|
|
43
|
-
| `
|
|
47
|
+
| `NERVUR_UNLOCK` | on macOS, `keychain:<account>` keeps the key in the keychain in place of `state/key` |
|
|
44
48
|
| `NERVUR_HAND` | where the hand's socket is, `state/hand` where unset; a relative path is read from where the command runs |
|
|
45
49
|
| `NERVUR_WAIT` | the longest any ask may run, in milliseconds |
|
|
46
50
|
|
|
@@ -58,18 +62,22 @@ Every other word goes to the ground's hand, a socket in `state/` that
|
|
|
58
62
|
your user alone may open. Run the command in the ground's folder, or
|
|
59
63
|
name the socket with `--at <socket>` or `NERVUR_HAND`.
|
|
60
64
|
|
|
61
|
-
`help` prints what the ground holds: each faculty with its methods,
|
|
62
|
-
each house.
|
|
65
|
+
`help` prints what the ground holds: each faculty with its methods, or
|
|
66
|
+
why it is down, and each house.
|
|
63
67
|
|
|
64
68
|
```bash
|
|
65
69
|
npx nervur help
|
|
66
70
|
```
|
|
67
71
|
|
|
68
72
|
A faculty is called by its name and a method. Named alone, it prints its
|
|
69
|
-
methods.
|
|
73
|
+
methods. Four faculties are the ground's own. `secrets` keeps a secret
|
|
74
|
+
in the ground's sealed drawer. `faculties` stands a faculty on the maker
|
|
75
|
+
its entry names, and `houses` opens a house on its entry.
|
|
70
76
|
|
|
71
77
|
```bash
|
|
72
|
-
npx nervur
|
|
78
|
+
npx nervur faculties add name=recipe make=module args='{"at":"recipe.ts"}'
|
|
79
|
+
npx nervur faculties add name=payments from=recipe make=payments secrets='["stripe-key"]'
|
|
80
|
+
npx nervur houses add name=main classes='{"body":"folder","at":"house"}' faculties='["payments"]'
|
|
73
81
|
```
|
|
74
82
|
|
|
75
83
|
`ask` asks a being of a house, as the house's owner. `--id <being>` names
|
|
@@ -101,6 +109,13 @@ JSON where it reads as JSON, and as text where it does not, so
|
|
|
101
109
|
npx nervur ask main hello '{"name":"Ada"}'
|
|
102
110
|
```
|
|
103
111
|
|
|
112
|
+
A lone `-` reads the one JSON object from standard input instead. So a
|
|
113
|
+
secret never stands on a command line or in a shell's history.
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npx nervur secrets set - < stripe-key.json
|
|
117
|
+
```
|
|
118
|
+
|
|
104
119
|
Each word prints one JSON value, the answer, and its exit code says what
|
|
105
120
|
came back.
|
|
106
121
|
|
package/FACES.md
CHANGED
|
@@ -188,25 +188,35 @@ method the tool's name, its args schema the tool's input schema, and its
|
|
|
188
188
|
hints the tool's annotations. A moved describe is a changed list of
|
|
189
189
|
tools.
|
|
190
190
|
|
|
191
|
-
## The
|
|
191
|
+
## The registry
|
|
192
192
|
|
|
193
|
-
The ground makes the face from
|
|
194
|
-
|
|
195
|
-
|
|
193
|
+
The ground makes the face from a registry, as it makes any faculty. A
|
|
194
|
+
NodeGround stands the module below with the maker `module`, and the
|
|
195
|
+
face from it by an entry that names `from`. The house's entry names
|
|
196
|
+
`face` among its faculties, and the steward's `arm` hands the face its
|
|
197
|
+
signup.
|
|
196
198
|
|
|
197
199
|
```ts
|
|
198
200
|
// recipe.ts
|
|
199
201
|
import { Api, apiOffer } from './api.ts';
|
|
200
202
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
203
|
+
// A registry: the ground makes the face when an entry names its maker.
|
|
204
|
+
export const faculties = {
|
|
205
|
+
face: () => apiOffer(new Api()),
|
|
206
|
+
};
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
npx nervur faculties add name=recipe make=module args='{"at":"recipe.ts"}'
|
|
211
|
+
npx nervur faculties add name=face from=recipe make=face
|
|
204
212
|
```
|
|
205
213
|
|
|
206
214
|
## Testing it
|
|
207
215
|
|
|
208
216
|
A BenchGround answers a request with its faculties' handlers in turn, as
|
|
209
|
-
a ground's one listener does, so the face is tested with no socket.
|
|
217
|
+
a ground's one listener does, so the face is tested with no socket. The
|
|
218
|
+
test hands the bench the registry, and stands the face through the
|
|
219
|
+
ground's hand, as an owner does.
|
|
210
220
|
|
|
211
221
|
```ts
|
|
212
222
|
// api.test.ts
|
|
@@ -217,8 +227,9 @@ import * as desk from './desk.ts';
|
|
|
217
227
|
import { faculties } from './recipe.ts';
|
|
218
228
|
|
|
219
229
|
test('A person signs up at the face, and reaches their member as an API and as tools', async (t) => {
|
|
220
|
-
const ground = await BenchGround.open({ network: new FakeNetwork(), host: 'desk', modules: { desk },
|
|
230
|
+
const ground = await BenchGround.open({ network: new FakeNetwork(), host: 'desk', modules: { desk }, registry: { faculties } });
|
|
221
231
|
t.after(() => ground.down());
|
|
232
|
+
await ground.hand({ faculty: 'faculties', method: 'add', args: { name: 'face', make: 'face' } });
|
|
222
233
|
await ground.add('desk', 'desk', { faculties: ['face'] });
|
|
223
234
|
await ground.ask({ house: 'desk', method: 'arm' });
|
|
224
235
|
const web = async (path: string, body?: unknown, token?: string) =>
|