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/LICENSE +2 -2
- package/README.md +151 -456
- package/package.json +12 -13
- package/src/being.js +125 -0
- package/src/contract.js +161 -0
- package/src/ground.js +273 -0
- package/src/index.js +5 -0
- package/src/program.js +74 -0
- package/src/projection.js +102 -0
- package/GETTING-STARTED.md +0 -111
- package/NOTICE +0 -2
- package/SECURITY.md +0 -11
- package/admin.mjs +0 -83
- package/being.mjs +0 -594
- package/blueprint.mjs +0 -462
- package/client.mjs +0 -70
- package/contract.mjs +0 -98
- package/ground.mjs +0 -381
- package/index.mjs +0 -20
- package/modules.mjs +0 -55
- package/pointer.mjs +0 -79
- package/program.mjs +0 -118
- package/tools.mjs +0 -162
- package/voice.mjs +0 -107
package/README.md
CHANGED
|
@@ -1,457 +1,152 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
`
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
the
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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.
|