nervur 0.17.0 → 0.18.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/README.md +30 -31
- package/package.json +2 -6
- package/GETTING_STARTED.md +0 -138
- package/protocol/SPEC.md +0 -1843
- package/protocol/vectors/arithmetic.json +0 -117
- package/protocol/vectors/door.json +0 -345
- package/protocol/vectors/framing.json +0 -92
- package/protocol/vectors/wire.json +0 -48
- package/quo-kit.md +0 -652
package/README.md
CHANGED
|
@@ -17,13 +17,16 @@ Nothing else is Quo.
|
|
|
17
17
|
beings and judges its door.
|
|
18
18
|
- **Being.** One ordinary object, one voice.
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
The truth is the spec, at <https://quo.systems/spec>, with the vectors it
|
|
21
|
+
is proved by at <https://quo.systems/vectors>. It is the protocol alone:
|
|
22
|
+
what any ward in any language must do for its bytes to be Quo. It is
|
|
22
23
|
self-contained and assumes nothing from any other document, this README
|
|
23
|
-
included. Read it first
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
included. Read it first, at the source, which is Quo's and not this
|
|
25
|
+
package's to carry.
|
|
26
|
+
|
|
27
|
+
What this one kit chose, and another kit may refuse, is documented at
|
|
28
|
+
<https://nervur.org/docs>. It assumes the spec, and where the two disagree
|
|
29
|
+
the spec wins.
|
|
27
30
|
|
|
28
31
|
## This package
|
|
29
32
|
|
|
@@ -33,8 +36,6 @@ source it was emitted from, because Node strips types nowhere under
|
|
|
33
36
|
`node_modules`.
|
|
34
37
|
|
|
35
38
|
```
|
|
36
|
-
protocol/ the shelf a kit in any language reads: SPEC.md and the vectors, no code
|
|
37
|
-
protocol/vectors/ fixed inputs and outputs, so another language proves its bytes
|
|
38
39
|
src/being/ the Being side: what a being author imports, if anything
|
|
39
40
|
src/ward/ the ward: the Ground contract, door, seal, arithmetic, heirs, stance, allowance
|
|
40
41
|
src/harbor/ MemoryHarbor, and the harbor core with its store, reach and dialer
|
|
@@ -74,32 +75,30 @@ import { Stand } from 'nervur/vector';
|
|
|
74
75
|
|
|
75
76
|
## Another language
|
|
76
77
|
|
|
77
|
-
The hand to a kit in another language is
|
|
78
|
-
|
|
79
|
-
nothing
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
`
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
Nothing outside that folder is the protocol. `src/` is this kit's
|
|
78
|
+
The hand to a kit in another language is Quo's own and not this package's.
|
|
79
|
+
The spec is the protocol and assumes nothing: a kit is written against it
|
|
80
|
+
and against nothing else. The vectors beside it are the byte-level hand,
|
|
81
|
+
everything a stranger can observe: `arithmetic.json`, the primitives the
|
|
82
|
+
seal rests on, SHA-256, Ed25519, X25519, HKDF and AES-256-GCM;
|
|
83
|
+
`framing.json`, Quo's own, the ward pk, the digest, the signed ask body,
|
|
84
|
+
the sealed shapes, the invitation and the knock; `wire.json`, the frames on
|
|
85
|
+
a socket and the one request a door takes; and `door.json`, the door's
|
|
86
|
+
thirteen cases, each one an arrival a ward will not answer, with the bytes
|
|
87
|
+
that arrive, the bytes that leave and the partition's digest on both sides
|
|
88
|
+
of the judgement. All of it is at <https://quo.systems>, downloadable and
|
|
89
|
+
versionless, and a kit reproduces the bytes or it is not this protocol.
|
|
90
|
+
|
|
91
|
+
`door.json` is also replayed from outside, by a verifier holding no key,
|
|
92
|
+
against a kit standing in vector mode, which the spec describes under that
|
|
93
|
+
name. This kit stands in it with `Stand` from `nervur/vector`, which is
|
|
94
|
+
vector mode and names no runtime: put it behind any listener that hands it
|
|
95
|
+
a request body and returns what it answers.
|
|
96
|
+
|
|
97
|
+
Nothing in this package is the protocol. `src/` is this kit's
|
|
99
98
|
interpretation, and `src/conformance/` is a checklist a kit ports rather
|
|
100
99
|
than a harness it runs: it imports the base class, the silence spelling and
|
|
101
100
|
this kit's store and reach, so the beings it is shown with run only in a
|
|
102
|
-
TypeScript ward.
|
|
101
|
+
TypeScript ward.
|
|
103
102
|
|
|
104
103
|
## Versions
|
|
105
104
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nervur",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Nervur's kit of Quo: an object asks another object and gets an answer, without knowing where it is. Being, Ward, Harbor, with the spec inside.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"quo",
|
|
@@ -39,11 +39,10 @@
|
|
|
39
39
|
"types": "./dist/vector/index.d.ts",
|
|
40
40
|
"default": "./dist/vector/index.js"
|
|
41
41
|
},
|
|
42
|
-
"./protocol/*": "./protocol/*",
|
|
43
42
|
"./package.json": "./package.json"
|
|
44
43
|
},
|
|
45
44
|
"scripts": {
|
|
46
|
-
"build": "rm -rf dist
|
|
45
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
47
46
|
"check": "node --test \"test/*.test.ts\"",
|
|
48
47
|
"deep": "node --test \"test/terrain/*.test.ts\"",
|
|
49
48
|
"prepublishOnly": "test \"$NERVUR_GATED\" = 1 || { echo 'publish from the root, gated once: npm run release:nervur' >&2; exit 1; }"
|
|
@@ -54,9 +53,6 @@
|
|
|
54
53
|
"files": [
|
|
55
54
|
"dist",
|
|
56
55
|
"src",
|
|
57
|
-
"protocol",
|
|
58
|
-
"quo-kit.md",
|
|
59
|
-
"GETTING_STARTED.md",
|
|
60
56
|
"README.md",
|
|
61
57
|
"LICENSE",
|
|
62
58
|
"NOTICE"
|
package/GETTING_STARTED.md
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
# Getting started
|
|
2
|
-
|
|
3
|
-
Quo lets an object ask another object and get an answer, without knowing
|
|
4
|
-
whether that other object is in the same process, on the same device, or
|
|
5
|
-
on another planet. Three words: a harbor boots wards, a ward keeps beings
|
|
6
|
-
and judges its door, and a being is one ordinary object with one voice.
|
|
7
|
-
This is the shortest road from nothing to each of the three, for a
|
|
8
|
-
stranger with a terminal. `SPEC.md` is the truth behind every sentence
|
|
9
|
-
here and assumes nothing; `quo-dock.md` is the dock, the part a box runs.
|
|
10
|
-
|
|
11
|
-
Quo is the protocol and Nervur is this kit of it. Every name you install
|
|
12
|
-
and every command you type is Nervur's; `quo` stays on the wire, as the
|
|
13
|
-
`quo.` route a ward's door answers at.
|
|
14
|
-
|
|
15
|
-
Two packages, and you start with the one that fits what you have:
|
|
16
|
-
|
|
17
|
-
- `nervur`, the library. A harbor, a ward and a being in one
|
|
18
|
-
process, no wire, no files. For a program that wants Quo inside it.
|
|
19
|
-
- `@nervur-org/dock`, the dock. A daemon and one command, `nervur`, that
|
|
20
|
-
stand a box up: a person's world with a page, a model's side, an api, a
|
|
21
|
-
door on the wire. For a box that receives people and models.
|
|
22
|
-
|
|
23
|
-
The command is in the dock and not in the library, so `npm install nervur`
|
|
24
|
-
gives you something to import and no command, and the command arrives with
|
|
25
|
-
`npm install -g @nervur-org/dock`. That is how a kit of this shape is
|
|
26
|
-
always named: one unscoped headline name for the library, the parts under
|
|
27
|
-
the scope, and the CLI in the package that owns it.
|
|
28
|
-
|
|
29
|
-
## A being, in one process
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
npm install nervur
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
A being is a class with `asks`, the methods anyone may reach, each with
|
|
36
|
-
the JSON schema of its input. Everything else on the class is hers alone.
|
|
37
|
-
|
|
38
|
-
```js
|
|
39
|
-
import { Being } from 'nervur';
|
|
40
|
-
import { Ward } from 'nervur/ward';
|
|
41
|
-
import { MemoryHarbor } from 'nervur/harbor';
|
|
42
|
-
|
|
43
|
-
class Shop extends Being {
|
|
44
|
-
static asks = { price: { input: { type: 'object', properties: { item: { type: 'string' } } } } };
|
|
45
|
-
price({ item }) {
|
|
46
|
-
return { item, eur: 12 };
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
class Customer extends Being {
|
|
50
|
-
static asks = {};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const harbor = new MemoryHarbor();
|
|
54
|
-
const ward = await harbor.boot('acme', Ward, { Shop, Customer });
|
|
55
|
-
await ward.ask('boot', { key: 'shop', class: 'Shop' });
|
|
56
|
-
await ward.ask('boot', { key: 'ana', class: 'Customer' });
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
The harbor booted a ward named `acme` with two classes it may make beings
|
|
60
|
-
of, and the ward's owner, the process itself, booted one of each by key.
|
|
61
|
-
The ward's own asks are seven, `boot`, `public`, `invite`, `knock`,
|
|
62
|
-
`remove`, `unboot` and `ask`, and `ward.ask()` with no method is her
|
|
63
|
-
describe: those asks and her `notes`, the ward's `pk` and her beings.
|
|
64
|
-
|
|
65
|
-
Nobody reaches a being she has not invited. An invitation is minted on a
|
|
66
|
-
being for one id, the shop's for `ana`, and the customer knocks with it;
|
|
67
|
-
from then she holds a standing at the shop, under the name she took, and
|
|
68
|
-
the shop holds her as an occupant.
|
|
69
|
-
|
|
70
|
-
```js
|
|
71
|
-
const invitation = await ward.ask('invite', { being: 'shop', id: 'ana' });
|
|
72
|
-
const ana = harbor.objects.get(harbor.partitions.get('acme').beings.ana);
|
|
73
|
-
await ana.knock(invitation);
|
|
74
|
-
await ana.take('shop', invitation);
|
|
75
|
-
console.log(await ana.standings.shop.ask('price', { item: 'bread' }));
|
|
76
|
-
// { item: 'bread', eur: 12 }
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
That is the whole protocol: a standing on one side, an occupant on the
|
|
80
|
-
other, an ask that rides the relation and an answer that rides it back.
|
|
81
|
-
The two beings here share a process; the same lines hold when the shop is
|
|
82
|
-
on a box across the sea, because a standing is an address and a key, and
|
|
83
|
-
the harbor owns the wire. `harbor.objects` is the memory harbor's hand for
|
|
84
|
-
a test and a first program; a being on a real box is reached through her
|
|
85
|
-
ward, never held.
|
|
86
|
-
|
|
87
|
-
## A box
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
npm install @nervur-org/dock
|
|
91
|
-
npx nervur init --dir ~/.nervur --ward acme --user razvan --domain acme.com --default --show
|
|
92
|
-
npx nervur serve --dir ~/.nervur --http 8787
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
`init` mints the ward `acme`, boots razvan's user being, her doorbell and
|
|
96
|
-
the desk in it, marks it the default ward and shows it at the web route,
|
|
97
|
-
and writes `routes.json`, the four routes of a box, `mcp.`, `web.`, `quo.`
|
|
98
|
-
and `api.` under the domain, for a proxy to map onto the one loopback
|
|
99
|
-
port. Without `--domain`, write it yourself; on a Mac the four are paths
|
|
100
|
-
at one loopback address:
|
|
101
|
-
|
|
102
|
-
```json
|
|
103
|
-
{ "mcp": "http://127.0.0.1:8787/mcp", "web": "http://127.0.0.1:8787/web", "quo": "http://127.0.0.1:8787/quo", "api": "http://127.0.0.1:8787/api" }
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
`serve` is the daemon, the one process over that folder, and every other
|
|
107
|
-
command is its client. From a second terminal, a phone:
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
npx nervur invite --dir ~/.nervur '{"being":"razvan","id":"phone"}'
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
The answer carries `link`, the ward's page with the invitation in its
|
|
114
|
-
fragment. Opened on the phone, the tab boots a harbor of its own, joins as
|
|
115
|
-
that device, and is in: no account, nothing typed. What a model gets is
|
|
116
|
-
the same world as tools at `mcp.`, what a program gets is the same asks as
|
|
117
|
-
JSON at `api.`, and what another box gets is the door at `quo.`; a being
|
|
118
|
-
answers each the same, because each is an ask at her door.
|
|
119
|
-
|
|
120
|
-
The box's own doings are rows on the faculties of its dock ward, placed by
|
|
121
|
-
the root with `nervur ask --ward dock`: a socket held to another box, an
|
|
122
|
-
agent run for a ward, a schedule on the clock. A second box owns this one
|
|
123
|
-
across the wire with an invitation on the ward's own pk, knocked with
|
|
124
|
-
from there, and every owner command with `--via` from then on. Each of
|
|
125
|
-
those, the edge, and what an estate stands beyond the init, is the
|
|
126
|
-
"Getting started" chapter of `quo-dock.md`, proven cold on a Mac by
|
|
127
|
-
somebody with nothing else to read.
|
|
128
|
-
|
|
129
|
-
## Your own beings on a box
|
|
130
|
-
|
|
131
|
-
A box holds the dock's classes and yours. `classes/index.ts` beside the
|
|
132
|
-
wards exports each of yours by name, and `nervur boot '{"key":"shop",
|
|
133
|
-
"class":"Shop"}'` boots one; `nervur init --class Shop` makes the ward's home
|
|
134
|
-
being one of yours, an organisation's ward with the org as its being. A
|
|
135
|
-
being's asks may name who may reach them, `for`, over the record of the
|
|
136
|
-
occupant asking, and her `cells` are what she keeps between boots: the
|
|
137
|
-
whole of what a being is, in `SPEC.md`, and the words above the spec, a
|
|
138
|
-
world, a home, a membership, in `WORLDS.md` and `GLOSSARY.md`.
|