nervur 0.13.0 → 0.15.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 CHANGED
@@ -1,457 +1,152 @@
1
- # Nervur
2
-
3
- The library. Picture a castle: one gate, its own residents, its own law.
4
- **A ground is the castle** — one sovereign process holding many beings,
5
- exposing exactly one handler where every message for every resident
6
- arrives. You arrive at the gate, say _I am X_ with your signature, and
7
- whom you seek travels inside the letter; the castle answers or keeps
8
- silence, and a resident that refuses you looks exactly like one that
9
- never lived there. The castle's capabilities are its **modules** — a
10
- resident uses only what its blueprint declares — and the terrain under
11
- the castle is a **floor**: a browser tab, a Linux daemon, a phone, an
12
- edge worker. The castle is a castle wherever it is built.
13
-
14
- Beneath the picture, the mechanics: an address is its own verification
15
- key, authority is a signature, and every relationship is one ref with
16
- declared rights — so a reference cannot be forged and no ambient
17
- authority exists anywhere. The door asks by whose authority and refuses
18
- every other question. The lineage is the object-capability tradition —
19
- CapTP, the actor model — with one honest departure: the door verifies who
20
- is calling, and rights are declared per reference. Pure Crockford
21
- JavaScript — factory functions, closures for privacy, no `this`, no
22
- classes, frozen surfaces — with no `node:` import anywhere, so the twelve
23
- files run wherever JavaScript does; three dependencies (`graphql` for the
24
- one thing that would be madness to hand-roll, `@noble/curves` and
25
- `@noble/hashes` for the arithmetic every host must agree on).
26
-
27
- ## Quickstart
28
-
29
- New to the whole thing? [GETTING-STARTED.md](GETTING-STARTED.md) raises
30
- two castles on two terrains — a server and a browser tab — and has them
31
- speak; the bench drives that exact story. What follows here is the
32
- library alone.
33
-
34
- `npm install nervur` — what ships is this source, byte for byte. The
35
- package is a library and carries no command; a ground also needs a floor
36
- (`@nervur-org/floor-machine` here) — the library is the law and the
37
- shape, and a host is what it stands on;
38
- the `nervur` command on an operator's PATH belongs to the
39
- [`nervurd`](../nervurd/README.md) package, its name twin. Construction is
40
- synchronous; every call through a door — `pointer`, `mcp`, `gql`, and each
41
- function they hand back — is async. This runs today, lifted from the
42
- bench's own passing suites:
43
-
44
- ```js
45
- import { Cells, Cipher, Keychain } from '@nervur-org/floor-machine';
46
- import { Ground, Tools, Voice } from 'nervur';
47
-
48
- const DIARY = `({
49
- name: 'acme.diary',
50
- needs: { modules: [{ module: 'memory', contract: 'nervur.memory' }] },
51
- memory: { pages: { type: '[String!]', class: 'data' } },
52
- interface: \`
53
- type Query { pages: [String!] @rights(is: [SELF, MEMBER]) }
54
- type Mutation { write(line: String!): Int @rights(is: [SELF, MEMBER]) }
55
- \`,
56
- resolvers: {
57
- Query: { pages: (_, __, { modules }) => modules.memory.read('pages') ?? [] },
58
- Mutation: {
59
- write: (_, { line }, { modules }) => {
60
- const kept = modules.memory.read('pages') ?? [];
61
- kept.push(line);
62
- modules.memory.write('pages', kept);
63
- return kept.length;
64
- },
65
- },
66
- },
67
- })`;
68
-
69
- const secret = Buffer.from(process.env.NERVUR_SECRET, 'base64'); // 32 bytes, minted once with Tools.secret()
70
- const shelf = {
71
- cells: Cells({ file: 'ground.json' }),
72
- cipher: Cipher(),
73
- keychain: Keychain(secret),
74
- };
75
-
76
- const heir = Voice(); // keep this one somewhere the machine is not
77
- const self = Voice(Tools.digest(heir.pk)); // and hand the ground only this
78
- Ground(shelf).init(self.hand()); // once, ever — a fresh ground offers nothing else
79
-
80
- const ground = Ground(shelf); // now it stands, and answers
81
- const me = Voice(); // keep it: writeFileSync of me.pack(), or it dies with the process
82
- await ground
83
- .serve(self)
84
- .pointer('Ground')
85
- .then((it) => it.invite({ address: Tools.address(me.pk) }));
86
-
87
- const serve = ground.serve(me);
88
- const admin = await serve.pointer('Ground'); // a pointer is your rights at mint — re-mint after they change
89
- const diary = await admin.create({
90
- program: DIARY,
91
- refs: [{ address: Tools.address(me.pk), rights: 'MEMBER' }],
92
- });
93
- const mine = await serve.pointer(diary);
94
- await mine.write({ line: 'first entry' });
95
- console.log(await mine.pages()); // [ 'first entry' ]
96
- ```
97
-
98
- The rights enum here is the default (`SELF MEMBER STRANGER`); declare your
99
- own `enum Rights` in the interface to replace it. Reboot: construct the
100
- same `Ground` from the same two arguments — it wakes remembering, and
101
- offers no `init`, because the identity survived in the cells.
102
-
103
- **The wire, when a caller is remote.** An envelope is plain JSON:
104
-
105
- ```json
106
- {
107
- "from": "G…",
108
- "to": "G…",
109
- "seq": 1755170000000,
110
- "op": { "ask": { "source": "{ pages }", "variables": {} } },
111
- "sig": "base64 over canon({from, op, seq, to})"
112
- }
113
- ```
114
-
115
- The ops are `describe`, `introspect`, `ask`, `rotate`, `release`,
116
- `acceptInvite`. An answer is `{ body, sig }`, signed by the being asked —
117
- verify against `pkOf(to)`, which `Client` does for you. A refusal is no
118
- answer at all; how silence rides your transport (a 204, an empty body) is
119
- the host module's choice. The library never opens a socket: your host
120
- listens however it likes and hands each envelope to `receive` —
121
- [the bench's sky.mjs](../bench/sky.mjs) is the reference harness for
122
- wiring grounds together.
123
-
124
- **The runbook, honestly.** Back up two things: the cells and the keychain
125
- secret — together they are the whole ground. A lost secret is permanent
126
- loss: nothing decrypts. A stolen secret plus stolen cells is total
127
- compromise, and rekey does not exist yet — destroy and recreate is
128
- today's remedy. The bench README's honest limits carry every known gap;
129
- read them before production.
130
-
131
- ## The two halves
132
-
133
- **The server** is `Ground(Modules)` — modules are the whole of what a ground
134
- is handed, and the ground is exactly what they offer. The floor is `cells`
135
- (storage, including the one boot cell) and `keychain` (boot power as two
136
- operations, seal and unseal — the enclave's own shape once a phone hosts a
137
- ground); `paths`, `wire`, `contracts` and `blueprints` are
138
- taken if given; everything else is a module for programs. It installs itself
139
- the first time and boots from the same two forever after, and hands back
140
- three things while hiding everything it is made of:
141
-
142
- - `address` — its own admin being, aliased `Ground`.
143
- - `receive(envelope)` — the one handler. Every message for every being on the
144
- ground arrives here and routes on the envelope's `to`. An address the
145
- ground does not hold is silence. A host module that listens on a port, or
146
- an app shell that calls in process, hands its envelopes to this and
147
- nothing else — the library never opens a socket. `receive` answers the
148
- signed `{ body, sig }` or `undefined` for silence; over HTTP, carry the
149
- answer as the 200 response body and silence however you like (`nervurd`
150
- uses an empty `204`) — no status code carries meaning, and a caller
151
- trusts nothing but a verified signed answer.
152
- - `serve(voice)` — authority established once, and every face inherits it.
153
-
154
- A fresh ground has no identity, and no door for anyone to reach first: it
155
- offers `init(hand)` and nothing else — no `address`, no `receive`, no
156
- `serve`. Custody mints the voice off the machine, keeps the heir, and hands
157
- over `hand()` alone; a pack carrying its own successor is refused. The act
158
- is spent the moment it lands, and only `rotate(hand)` moves that voice
159
- after. Both are custody's own calls on the shelf, never doors — which is
160
- what running-is-custody looks like from the outside, stated rather than
161
- hidden.
162
-
163
- `unproven()` is custody's third call, and it is a read: the addresses whose
164
- writes have stopped proving, with when each was first and last seen and how
165
- many writes have been refused. A write is proven against the key on the
166
- being's `chain/pk` cell, so whoever holds the shelf can overwrite that cell
167
- and freeze a being's memory while it answers on, correctly signed and
168
- indistinguishable to every caller. The ground records that in its own host
169
- rows under `ground/` — no being reads them, nothing goes over the wire — and
170
- this is where a host reads them back. Show it to whoever operates the
171
- machine; a ground that has stopped proving its own writes is a custody
172
- incident, not a bug.
173
-
174
- **`serve` is the client, and it has four faces of one door.** `pointer(at)`
175
- is a plain object with one function per field, generated from the schema that
176
- caller is allowed to see. `gql(at)` is the raw document. `mcp(at)` is the
177
- same schema as tools, filtered the same way, so an agent gets exactly what
178
- its rights allow — a projection into JSON Schema, so scalar fields travel
179
- whole while unions and custom scalars flatten; the rights filtering happens
180
- on the SDL before the projection, so what flattens is shape, never
181
- permission. `client` is the bare envelope underneath all three. Each
182
- takes an address or an alias; each signs as the identity `serve` was given
183
- and verifies every answer against the address it asked.
184
-
185
- Delivery is local or remote through one API — a local answer and a remote
186
- one carry the same shape, and the calling code does not branch. Failure
187
- stays observable, as it always is: a missing endpoint or a dead ground is
188
- silence, and silence is something local delivery never answers with.
189
-
190
- ## The files
191
-
192
- - [tools.mjs](tools.mjs) — the world's arithmetic, one frozen literal, and it
193
- holds nothing: `digest`, `verifies`, `seal`/`unseal`/`secret`, `canon`
194
- (canonical bytes), `envelope` (the signed message, numbered), `derive` (a
195
- class key from a root), `address`/`pkOf` (StrKey, so every key is a Stellar
196
- account and an address is a verification key). Same input, same output, any
197
- machine — which is why an attacker computes all of it exactly as well as
198
- you do. Nothing here holds a key: `envelope` assembles and numbers the
199
- message and asks the voice it is handed to sign. Beside the literal stands
200
- `Stamp`, the one stateful thing in the file: each caller mints one and
201
- numbers its own envelopes, strictly rising. `Client` and a being's port
202
- keep one lane per counterparty, so concurrent calls to the same door
203
- land in order on their own; only a bare-envelope caller orders its own.
204
- - [voice.mjs](voice.mjs) — the identity: three private keys shut in a closure
205
- and never reachable from outside. `Voice()` mints one already committed to
206
- its own successor, `Voice.revive` wakes a packed one, `Voice.sealTo` seals
207
- to a voice's box key and `voice.open` is the only thing that opens it.
208
- `succeed()` retires both hands at once — the committed key starts speaking
209
- and a fresh box starts reading. The re-wrap is the handover's own
210
- choreography: the retiring voice still stands when `succeed()` returns, so
211
- the holder opens with the old box and seals to the new one in the same
212
- act, then discards the old voice — after which it opens nothing that
213
- remains. `pack()` is the one door out — the ground's custody, and
214
- precisely why hosting is custody.
215
- - [blueprint.mjs](blueprint.mjs) — the blueprint law. A program is compiled
216
- from one serialisable source with no identity, no ground and no ambient
217
- power in it: forbidden names are refused where they are read as powers and
218
- shadowed at evaluation, the modules and bindings it needs are declared and
219
- typed, the cells it keeps are declared with their class, its rights are its
220
- own and every door declares them — a root field without `@rights`, or one
221
- naming a right the enum never declared, is refused at compile — and the
222
- whole of it digests to one canonical hash, rights included. Reformatting
223
- the schema does not move the digest; a resolver digests by its source
224
- text, so reformatting the code mints a new program. The forbidden-name
225
- scan is a code-only regex, not a parser — a bounded blast radius, stated
226
- as such, never a jail.
227
- - [program.mjs](program.mjs) — a blueprint made executable: every field
228
- gated by the `@rights` it declares, resolver or no resolver, and
229
- introspection curtained per caller exactly as describe is. Errors never
230
- leave the house.
231
- - [modules.mjs](modules.mjs) — what a ground offers. `Cells` is dumb storage,
232
- optionally a file. `Memory` is the memory law: reads free, writes signed by
233
- the compartment's current voice, one version per cell, the chain by
234
- prove-and-replace. `Clock` and `Entropy` are pinnable, so a program need
235
- never reach for the wall. `Paths` resolves an address to an endpoint and
236
- vouches for nothing; `Wire` carries; `Dns` is the directory they share.
237
- - [contract.mjs](contract.mjs) — an interface with a digest and nothing else.
238
- What `needs.modules` cites, what a bound module's client is generated from,
239
- and what `attest` judges a stander by: more than the contract asks is fine,
240
- less is not.
241
- - [pointer.mjs](pointer.mjs) — `Pointer` and `Mcp`, both read off an SDL, so
242
- no client is ever written by hand for a program.
243
- - [client.mjs](client.mjs) — the bare envelope client, usable on its own.
244
- Signs as its voice, and verifies every reply from the address alone:
245
- `pkOf(to)` is the key the being was born with, and each handover the reply
246
- carries in `succession` is checked against the key before it, so a being
247
- that has rotated is still provably itself to a caller that has never met
248
- it. A chain that breaks anywhere is a dropped answer.
249
- - [being.mjs](being.mjs) — the being. `Compartment` seals a cell by its
250
- class, `Port` carries authority both ways, `Being` is the door — prove,
251
- read rights, execute, sign — and `Registry` creates, takes custody of,
252
- activates and destroys, reachable only through the admin being.
253
- - [admin.mjs](admin.mjs) — the administrative program every ground installs
254
- for itself, aliased `Ground`: census, create, activate, destroy, upgrade,
255
- alias, attest, invite, drop, wear, and behind `SELF` alone extend; `wears`
256
- answers any stranger with the livery being the ground wears. Upgrade is
257
- custody moving the one cell that was always the core's to move: the
258
- program is replaced in place — address, cells, refs and chain surviving —
259
- refused whole when a cell the being holds would go undeclared, and visible
260
- to every peer because `describe` answers the program's digest. It refuses
261
- the ground's own address; that program moves only through `extend`, which
262
- takes the custom part alone and lets the core compose it with the fixed
263
- administration.
264
- - [ground.mjs](ground.mjs) — the sovereign ground, its one handler and
265
- `serve`.
266
- - [index.mjs](index.mjs) — the surface an adopter imports.
267
-
268
- ## The two reference tables
269
-
270
- A being keeps one row per direction, and nothing anywhere keeps a shared
271
- record of the relation.
272
-
273
- - **`refs/`** — who refers to me, and with what rights. This is the inbound
274
- reference table: each entry is one capability the being issued, plus the
275
- highest envelope number seen from that holder — which is what makes a
276
- captured envelope worthless. A holder drops its own row with `release`;
277
- the door answers it like any op and the row is gone for good.
278
- - **`handles/`** — whom I refer to, and under which face. Outbound, and the
279
- face is a keypair minted per counterparty, so no two peers can correlate
280
- the same being by its keys — timing and shape stay visible to whoever
281
- already sees them.
282
-
283
- ## Classes, not tiers
284
-
285
- No super-user stands inside the system — no voice passes every door. The
286
- host running the ground is custody, not a user: root on the live process
287
- holds everything, and stands outside every claim made here (the bench's
288
- honest limits say it whole). A `class` here is a cell's sealing class,
289
- never a JavaScript class — the code has none. A being holds one root
290
- secret, and every class of
291
- cell seals with a key derived from it — so a leaked class key opens one
292
- class. Today no path hands out a class key without the root: the partition
293
- prices a future delegation of reading and bounds a bug, it does not defend
294
- against a present leak. A blueprint declares which cells it keeps and under which class, and a
295
- resolver may write only those, plus its own refs and handles. Its program,
296
- its chain and its keys are the core's to move, never its own.
297
-
298
- ## What an adopter brings
299
-
300
- Their own modules, their own programs, their own keys. A program names the
301
- contracts it needs and runs on any ground that stands them — as a module, or
302
- as a being, on this ground or another. A ground missing one refuses the
303
- creation rather than failing later. The regress ends at one cell: the ground
304
- needs just enough local storage to hold its own seed and where everything
305
- else lives.
306
-
307
- ## The floor — what is mandatory, what is yours
308
-
309
- `Ground(Modules)` reads exactly seven names from what you hand it; every
310
- other name passes through untouched as a module for programs.
311
-
312
- - **`cells` — mandatory.** The shelf: `peek`/`put`/`keys`/`drop`/`dump`,
313
- key to value, nothing else. Ships as a Map, optionally mirrored to one
314
- JSON file. Swap it for anything that keeps those five promises
315
- **synchronously, to a single writing process** — SQLite through a
316
- synchronous driver, localStorage in a tab — the memory law versions
317
- writes, it does not lock them, so exactly one ground writes a shelf. A
318
- shared or remote store is never a cells swap: it stands behind its own
319
- door as a memory being (bench suite 8), whose own ground is the single
320
- writer of its own shelf. What sits on it: sealed content, the
321
- deliberately unsealed
322
- blueprints, and the shape — names, sizes, versions, timing. Sealed
323
- content is safe wherever the shelf lives; the shape and the program
324
- source are readable by whoever holds it, so where it lives decides who
325
- sees those.
326
- - **`keychain` — mandatory.** Two operations, `seal` and `unseal`, guarding
327
- the one cell that boots the ground — the ground hands its boot cell to
328
- the keychain and never sees a secret at all. `Keychain(secret)` builds
329
- one from 32 bytes; a KMS stands behind the same two operations as an API
330
- call; the Secure Enclave stands behind them natively, because sealing
331
- without exporting the key is exactly what such hardware does. Choosing
332
- the keychain is the host's one security decision: a root-only file
333
- restarts unattended and dies with the disk image; a KMS can refuse the
334
- next boot — revocation stops tomorrow, it does not evict a thief who
335
- already copied (rekey is owed; the bench's honest limits carry it); the
336
- Enclave keeps the power in the device, and it never leaves. A keychain
337
- that cannot unseal yields no ground at all.
338
- - **`paths` — optional; defaults to a private in-memory map.** The
339
- phonebook: `publish`/`find`, address to endpoint, and it vouches for
340
- nothing — a poisoned phonebook makes a being unreachable, never
341
- impersonated, because the address verifies every answer.
342
- - **`wire` — optional; defaults to in-process delivery.** The courier:
343
- `carry(endpoint, envelope)`. The library never opens a socket — a host
344
- module listens on whatever transport it likes and hands envelopes to
345
- `receive`; the wire carries the outbound ones.
346
- - **`contracts` — optional; empty by default.** The dictionary of
347
- interfaces this ground can attest. Required the moment a module is bound
348
- by address, so that `memory` offers the same interface under the same
349
- digest on every ground and a pretender is refused. A digest pins shape;
350
- what the words mean is the contract author's prose to state.
351
- - **`blueprints` — optional.** `blueprints.ground()` seeds the
352
- administration's custom part at install. After that the part moves only
353
- through the `extend` door, so a host that keeps its blueprint in a file
354
- and hands it over with the CLI never needs this slot at all.
355
- - **`watch` — optional.** The custodian's eye: a function called at every
356
- door decision with one frozen fact, `{ to, from, kind, outcome }`, and
357
- the outcomes are a closed set — `no-door`, `unproven`, `replayed`,
358
- `mute`, `answered`. It sees outcomes and outsides, never an op body and
359
- never a cell — exactly as knowing as the host already is. The caller's
360
- silence is untouched; a watch that throws changes nothing; no watch
361
- costs nothing. Tracing, metrics and logs are a host package built on
362
- this, never the library's.
363
-
364
- Boot, in order: a ground over an empty shelf offers `init(hand)` alone.
365
- Given the hand, it writes the admin being and seals that voice into one cell
366
- under the keychain. Every boot after: the keychain unseals, the voice
367
- revives, every being in custody is announced, the ground answers.
368
- `rotate(hand)` is the only thing that moves that voice, and it certifies the
369
- handover so every caller follows the ground from its address. `Clock` and
370
- `Entropy` are not floor: they are ordinary modules a program declares,
371
- pinnable so a program never reaches for the wall.
372
-
373
- ## Extending the administration
374
-
375
- A ground's administration is a being like any other, and the only one whose
376
- context holds the registry — so a door that must create, upgrade or destroy
377
- beings belongs on it and nowhere else. Adopters extend it; nobody replaces
378
- it.
379
-
380
- Hand the custom part to the `extend` door — `SELF`'s alone — and the core
381
- composes it with the standard administration. What you supply is the part by
382
- itself, never the whole program, so the acts this ground owes can never go
383
- missing. The same door replaces the part and removes it. Write it as an
384
- ordinary blueprint whose schema **extends** the roots:
385
-
386
- ```js
387
- const cases = `({
388
- name: 'procese.cases',
389
- needs: { caller: true, modules: [{ module: 'memory', contract: 'nervur.memory' }] },
390
- memory: { 'case/*': { type: 'String', class: 'data' } },
391
- interface: \`
392
- extend type Mutation {
393
- openCase(title: String!): String @rights(is: [SELF, MEMBER])
394
- }
395
- \`,
396
- resolvers: {
397
- Mutation: {
398
- openCase: (_, { title }, { from, modules, registry }) => {
399
- const at = registry.create({ program: CASE, refs: [{ address: from }] });
400
- modules.memory.write('case/' + at, title);
401
- return at ?? null;
402
- },
403
- },
404
- },
405
- })`;
406
-
407
- await ground
408
- .serve(self)
409
- .pointer('Ground')
410
- .then((it) => it.extend({ program: cases }));
1
+ # nervur
2
+
3
+ Nervur grown on the working Quo kit. It imports `@quo-systems/js` and adds no
4
+ protocol
5
+ of its own — no wire, no envelope, no judgment, no arithmetic, ever. What
6
+ Nervur is for begins where the constitution stops: the graph, the organs, the
7
+ floor, and the projection from an authored contract into Quo blueprints.
8
+
9
+ ## The rules of this build
10
+
11
+ 1. **`@quo-systems/js` is the whole of the protocol.** It is crossed by its
12
+ specifier,
13
+ never by a path. A gap the kit shows is reported to the quo table, never
14
+ patched here.
15
+ 2. **nervur-dream is parked beside this, as reference.** Its mechanics may be
16
+ lifted — the compiler, the contract reader, the `@needs` directive. Its
17
+ judgement may not: what a thing enforces, refuses or means is authored fresh
18
+ against the constitution as it stands today, because dream was built against
19
+ a protocol that no longer exists.
20
+ 3. **Crockford.** Factory functions, closures for privacy, no `this`, frozen
21
+ surfaces. The kit's class idiom stops at its specifier: the ground factory
22
+ is the one place a `Warden` instance lives, closed over and never returned.
23
+ 4. **One played bench question at a time.** Doubt is settled on the bench, not
24
+ argued. Nothing lands without an assert that would fail if it broke.
25
+ 5. **A being never learns who is calling, but it knows who may reach it.** The
26
+ first half is the kit's doing: the warden places a voice at step three and
27
+ hands the field its arguments and its leash, never the caller. Which being
28
+ was reached already says who called. The second half is Nervur's: the warden
29
+ keeps the record of which voices reach which beings, and a being is handed
30
+ its own row to read and to change. No rights and no roles — those are
31
+ meanings, and the record holds none.
32
+
33
+ ## What stands
34
+
35
+ **`ground()`** — one closure over one warden, holding beings and judging what
36
+ arrives. `bench/ground.test.js` walks it end to end: a real sealed ask, a real
37
+ answer, and silence where a standing does not reach.
38
+
39
+ **The outbound relation** — `remember` records an invitation this ground was
40
+ handed and names which of its beings spends it; `ask` seals down that relation,
41
+ posts it at the hints the invitation carried, and reads the answer back. Every
42
+ one of those acts is the kit's. What is Nervur's is the ergonomics: a relation
43
+ is found by whose it is, so one being cannot spend another's; the number is the
44
+ ground's to pick, so no caller counts by hand; and the first ask carries the
45
+ rotation an invitation's heir keys oblige, so nobody meets that trap twice.
46
+ `bench/estate.test.js` stands two houses on two real loopback doors and crosses
47
+ between them.
48
+
49
+ Silence, unreachable and a relation that is not yours are three different
50
+ things and stay three: silence is `null`, a road that does not answer throws
51
+ out of the carriage, and spending what a being does not hold throws before a
52
+ byte moves.
53
+
54
+ **`contract(sdl)` and `program(contract, resolvers)`** — the compiler, and
55
+ there is exactly one of it. A being and an organ are both a contract plus
56
+ resolvers, and `program` cannot tell which it is holding; that is not a
57
+ convenience, it is the architecture. A field is read with `hasOwn` and never
58
+ through the prototype chain, exactly the declared arguments reach a resolver
59
+ and no others, a resolver short of a required argument is not called at all,
60
+ and a resolver that throws is answered as silence — nothing here promises that
61
+ an ask is fulfilled, so a refusal a caller must tell apart is carried in the
62
+ answer type instead. `bench/program.test.js` asserts every one of those, and
63
+ asserts the first on a being and an organ side by side.
64
+
65
+ **The contract is a GraphQL schema** — schema, resolvers and a context, the
66
+ shape every engineer already knows. It is authoring and nothing else: never at
67
+ the wire, never an answer, never a describe. The organs a being reaches outward
68
+ with are declared in the schema itself, with `schema @needs(organs: [...])`,
69
+ and the being's own name is the root type's — `schema { query: Clerk }`.
70
+
71
+ **`project(contract)`** — the boundary, and there must be exactly one of it.
72
+ Every implementer of Quo speaks the notation and has never heard of Nervur, so
73
+ a contract becomes a Quo blueprint in the kit's own notation before anything
74
+ holds it, and what a stranger verifies is that blueprint's digest. GraphQL is
75
+ nullable by default and the notation is required by default, so `String!`
76
+ becomes `text` and `String` becomes `text?`; the schema's other object and
77
+ input types become record blocks, and their ordering is the notation's own law
78
+ and therefore the kit's `print` to judge. Where GraphQL says something the
79
+ notation has no word for — `Float`, `ID`, an enum, a union, an interface, a
80
+ record field that takes arguments — the contract is refused at build rather
81
+ than guessed at. One word runs the other way: the notation has a field that
82
+ answers nothing and GraphQL insists every field has a type, so `Nothing` in
83
+ answer position is that field's spelling. `bench/projection.test.js` holds it.
84
+
85
+ **`being(sdl, resolvers)`** — a schema and ordinary functions under it. It is
86
+ compiled by `program` like anything else; what it adds is the wire skin the kit
87
+ leaves open, and the two promises the kit leaves to Nervur: a resolver meets
88
+ its arguments as named values and never bytes, and a being answers **exactly**
89
+ the fields its contract declares. That second one is the gate the digest's
90
+ meaning rests on — the law says what a blueprint does not declare does not
91
+ exist, and the kit dispatches on whatever methods the held object happens to
92
+ have.
93
+
94
+ **Organs** — the only way a being _acts_ outward. That is not a style choice:
95
+ a being has no warden and no caller, so it cannot mint standing and a field
96
+ answering another being's name hands over a label rather than reach. What it
97
+ can still do is pass on standing it was already given — the constitution says
98
+ data can carry an `invitation`, and an invitation carries the heir keys — so
99
+ "a being cannot hand over reach" is false as a general claim and only the
100
+ minting half is true. A being names the organ aliases it needs in its own
101
+ schema, the ground supplies them at `hold`, and the resolvers are closed over
102
+ exactly those. An organ the schema never asked for is not absent from a check —
103
+ it is absent from the object.
104
+
105
+ **The organ that crosses** — `errand` mints the reach a being uses to speak to
106
+ another house. It is shut over which being spends the relation and which house
107
+ it stands at, so a being holds one road on its own behalf and nothing it could
108
+ point elsewhere; it never holds the warden and never holds the relation. Which
109
+ being at the far house is still the caller's to name, because the standing
110
+ decides that and the standing is judged over there. The **leash** is handed in
111
+ rather than chosen — the resolver passes on the one the door gave it, whole and
112
+ never a number read off it, because what may go onward is this door's dwell
113
+ subtracted at the moment of sealing, which is later than any moment the being
114
+ could have read. So the remainder reaches the far house without the being
115
+ having chosen it, and a being cannot hand its organ more than it received.
116
+ `bench/errand.test.js` serves one sealed ask at the near house by crossing to
117
+ the far one and answering with what came back.
118
+
119
+ **Contacts** — who reaches this being, and the two acts that change it:
120
+ `list()`, `admit(keys)` and `remove(voicePk)`. Every one of them goes to the
121
+ warden's own inbound record — `grant`, `amend`, `standing` — read live at the
122
+ moment it is called and never snapshotted, so a being that admitted someone a
123
+ moment ago sees them. Quo keeps that record and refuses to have an opinion
124
+ about it, having no word for member, owner or guest; the opinion is Nervur's,
125
+ and this is the whole of it. The inverse — voices by being, where the warden
126
+ keeps beings by voice — is derived rather than indexed, because a second index
127
+ is a second truth.
128
+
129
+ The scoping is structural, the same shape `errand` uses: the context is minted
130
+ per `hold` with the being shut inside the closure, so there is no address it
131
+ could name to reach another being's row. It reaches a resolver as the resolver
132
+ factory's second argument, closed over at raise beside the organs, rather than
133
+ as a third argument to every resolver. `bench/contacts.test.js` proves the
134
+ admission and the removal at the door — a real sealed ask that gets in, and
135
+ then meets silence.
136
+
137
+ Organs are declared inside the contract, with `schema @needs(organs: [...])`.
138
+ That directive is authoring and never reaches the wire: the projection drops
139
+ it, so the blueprint a stranger reads carries no trace of what a being reaches
140
+ outward with, which is inside-the-ground business the wire never sees.
141
+
142
+ ## What is not here yet
143
+
144
+ `own` and the floor, memory, standings and the graph walked across them, the
145
+ per-call caller, ground-as-a-folder, persistence, register-and-invoke,
146
+ collections-as-beings, per-caller beings.
147
+
148
+ ## The bench
149
+
150
+ ```bash
151
+ npm run gate-nervur
411
152
  ```
412
-
413
- The composed program is one blueprint with one digest, so `describe` answers
414
- what this ground's administration actually is, and an outsider can pin it.
415
-
416
- Three rules hold, and each refuses the whole extension rather than bending:
417
-
418
- 1. **Standard door names are reserved.** Declare `create`, `census`,
419
- `upgrade`, `destroy`, `alias`, `attest`, `opened`, `invite`, `drop` or
420
- `extend` and the part is refused. You cannot change what a standard door
421
- means — which is why a stranger may trust that if `create` answers, it
422
- created.
423
- 2. **Add only.** Use `extend type Query` / `extend type Mutation`; cell
424
- names, module slots and `needs.config` may not collide with the
425
- administration's own.
426
- 3. **Close a door the way anything is closed here** — fence it behind a
427
- right the ground never grants. The door stands, means what the
428
- constitution says, and answers nobody: that is how an appliance ground
429
- stops creating beings, without redefining a thing.
430
-
431
- The acts stay the core's own: an extension reaches them through the same
432
- registry face the standard doors use, so it can invent no power the standard
433
- administration lacked.
434
-
435
- ## Writing a module
436
-
437
- Five rules, each load-bearing:
438
-
439
- 1. **A frozen object of functions and nothing else** — no classes, no
440
- events, no state a being could share through it. State belongs behind a
441
- door: a stateful module is a being with cells of its own, bound by
442
- address under rule 5.
443
- 2. **Params carry the authority.** The module holds no account, no key, no
444
- ambient context: `stripe.charge({ account, apikey, amount })`. This is
445
- what makes the same module safe to hand to every being on the ground —
446
- without the context it opens nothing.
447
- 3. **It knows nobody.** A module never learns which being calls; per-being
448
- authority arrives through the blueprint's declared bindings, typed, with
449
- a declared owner.
450
- 4. **Undefined is refusal** — the same silence the door speaks, never an
451
- error that narrates.
452
- 5. **A module blueprints will name needs a contract** — the interface whose
453
- fields mirror its calls, digested, so the same word means the same thing
454
- on every ground. The ground attests a stander against it: more than the
455
- contract asks is fine, less is not. A module a being stands remotely is
456
- bound as `{ at, contract }`; the floor — cells, keychain, paths, wire —
457
- is host code, because it must exist before any being can speak.