nervur 0.14.0 → 0.16.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 CHANGED
@@ -1,3 +1,4 @@
1
+
1
2
  Apache License
2
3
  Version 2.0, January 2004
3
4
  http://www.apache.org/licenses/
@@ -186,7 +187,7 @@
186
187
  same "printed page" as the copyright notice for easier
187
188
  identification within third-party archives.
188
189
 
189
- Copyright [yyyy] [name of copyright owner]
190
+ Copyright 2026 Razvan Gherghina
190
191
 
191
192
  Licensed under the Apache License, Version 2.0 (the "License");
192
193
  you may not use this file except in compliance with the License.
package/NOTICE CHANGED
@@ -1,2 +1,6 @@
1
- Nervur
1
+ Quo
2
2
  Copyright 2026 Razvan Gherghina
3
+
4
+ This product includes software developed by Razvan Gherghina.
5
+
6
+ Licensed under the Apache License, Version 2.0. See LICENSE for the terms.
package/README.md CHANGED
@@ -1,457 +1,32 @@
1
- # Nervur
1
+ # nervur
2
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.
3
+ Quo is a protocol that lets an object ask another object and get an answer,
4
+ without knowing whether that other object is in the same process, on the
5
+ same device, or on another planet. Nervur's kit is its first implementation,
6
+ open source, three packages under the `@nervur-org` scope.
13
7
 
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).
8
+ This package is the unscoped twin of that scope. `import` from it and you
9
+ have the library; run it and you have the dock's command:
26
10
 
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 }));
11
+ ```bash
12
+ npm install nervur
13
+ npx nervur init
411
14
  ```
412
15
 
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.
16
+ | Package | What it is |
17
+ | --- | --- |
18
+ | [`@nervur-org/nervur`](https://www.npmjs.com/package/@nervur-org/nervur) | the library: harbor, ward and being, the protocol itself, with the spec inside |
19
+ | [`@nervur-org/dock`](https://www.npmjs.com/package/@nervur-org/dock) | what every estate on Quo needs and nobody writes twice: the daemon, the command, the model sides and the screen |
20
+ | [`@nervur-org/ui`](https://www.npmjs.com/package/@nervur-org/ui) | the kit: one token contract, one baseline, and the primitives a screen and a website both need. Knows nothing of Quo |
430
21
 
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.
22
+ It pins the library and the dock exactly, so that the name stands for one
23
+ kit. Its own number counts up on its own, because a name and what it
24
+ stands for are two things. An estate that wants the pieces apart installs
25
+ them apart.
434
26
 
435
- ## Writing a module
27
+ <https://nervur.org> is the kit. <https://quo.systems> is the protocol.
436
28
 
437
- Five rules, each load-bearing:
29
+ ## License
438
30
 
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.
31
+ Apache-2.0. Copyright 2026 Razvan Gherghina. See [LICENSE](LICENSE) and
32
+ [NOTICE](NOTICE).
package/index.js ADDED
@@ -0,0 +1,17 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // The name, and what stands under it. This package is the unscoped twin of
3
+ // the `@nervur-org` scope: `import ... from 'nervur'` is the library, and
4
+ // `npx nervur` is the dock's command. It pins the two exactly, because a
5
+ // name that stands for the kit stands for one version of it.
6
+
7
+ export * from '@nervur-org/nervur';
8
+
9
+ /** The published packages, and what each one is. */
10
+ export const PACKAGES = Object.freeze({
11
+ '@nervur-org/nervur': 'the library: harbor, ward and being, the first kit of Quo',
12
+ '@nervur-org/dock': 'what every estate on Quo needs and nobody writes twice',
13
+ '@nervur-org/ui': 'the kit: one token contract, one baseline, the primitives',
14
+ });
15
+
16
+ /** Where to read what the kit is. */
17
+ export const HOMEPAGE = 'https://nervur.org';
package/nervur.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // `nervur`: the dock's command under the kit's name. Every subcommand is the
4
+ // dock's; this file only finds it.
5
+ import '@nervur-org/dock/cli';
package/package.json CHANGED
@@ -1,25 +1,42 @@
1
1
  {
2
2
  "name": "nervur",
3
- "version": "0.14.0",
4
- "description": "A distributed system of sovereign beings — one door, one question: by whose authority.",
5
- "license": "Apache-2.0",
3
+ "version": "0.16.0",
4
+ "description": "Nervur's kit of Quo, under one name: the library re-exported, and the dock's command as nervur. The packages are @nervur-org/nervur, @nervur-org/dock and @nervur-org/ui.",
5
+ "keywords": [
6
+ "quo",
7
+ "nervur",
8
+ "protocol",
9
+ "capability",
10
+ "object-capability"
11
+ ],
6
12
  "author": "Razvan Gherghina",
13
+ "license": "Apache-2.0",
7
14
  "homepage": "https://nervur.org",
8
15
  "type": "module",
16
+ "engines": {
17
+ "node": ">=22.18"
18
+ },
19
+ "bin": {
20
+ "nervur": "./nervur.js"
21
+ },
9
22
  "exports": {
10
- ".": "./index.mjs"
23
+ ".": "./index.js"
11
24
  },
12
- "files": [
13
- "*.mjs",
14
- "GETTING-STARTED.md",
15
- "NOTICE",
16
- "SECURITY.md"
17
- ],
18
- "engines": {
19
- "node": ">=22"
25
+ "scripts": {
26
+ "prepublishOnly": "test \"$QUO_GATED\" = 1 || { echo 'publish from the root, gated once: npm run release:nervur' >&2; exit 1; }"
20
27
  },
21
28
  "dependencies": {
22
- "@noble/curves": "2.3.0",
23
- "graphql": "^17.0.2"
24
- }
29
+ "@nervur-org/dock": "0.3.0",
30
+ "@nervur-org/nervur": "0.3.0"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "files": [
36
+ "index.js",
37
+ "nervur.js",
38
+ "README.md",
39
+ "LICENSE",
40
+ "NOTICE"
41
+ ]
25
42
  }