nervur 0.22.1 → 0.22.2-4

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.
Files changed (396) hide show
  1. package/AUTHORING.md +814 -0
  2. package/KIT-SPEC.md +286 -0
  3. package/README.md +128 -431
  4. package/dist/app/app-ground.d.ts +18 -0
  5. package/dist/app/app-ground.js +25 -0
  6. package/dist/app/index.d.ts +2 -0
  7. package/dist/app/index.js +5 -0
  8. package/dist/app/native.d.ts +46 -0
  9. package/dist/app/native.js +101 -0
  10. package/dist/being/being.d.ts +229 -0
  11. package/dist/being/being.js +20 -0
  12. package/dist/being/covers.d.ts +9 -0
  13. package/dist/being/covers.js +21 -0
  14. package/dist/being/index.d.ts +3 -0
  15. package/dist/being/index.js +5 -0
  16. package/dist/being/need.d.ts +49 -0
  17. package/dist/being/need.js +33 -0
  18. package/dist/being/schema.d.ts +100 -0
  19. package/dist/being/schema.js +132 -0
  20. package/dist/being/table.d.ts +42 -0
  21. package/dist/being/table.js +288 -0
  22. package/dist/bench/bench-ground.d.ts +55 -0
  23. package/dist/bench/bench-ground.js +101 -0
  24. package/dist/bench/bench.d.ts +87 -0
  25. package/dist/bench/bench.js +260 -0
  26. package/dist/bench/fake-carry.d.ts +32 -0
  27. package/dist/bench/fake-carry.js +56 -0
  28. package/dist/bench/fake-clock.d.ts +17 -0
  29. package/dist/bench/fake-clock.js +34 -0
  30. package/dist/bench/fake-custody.d.ts +9 -0
  31. package/dist/bench/fake-custody.js +10 -0
  32. package/dist/bench/fake-faculty.d.ts +25 -0
  33. package/dist/bench/fake-faculty.js +48 -0
  34. package/dist/bench/fake-keys.d.ts +5 -0
  35. package/dist/bench/fake-keys.js +9 -0
  36. package/dist/bench/fake-memory.d.ts +14 -0
  37. package/dist/bench/fake-memory.js +46 -0
  38. package/dist/bench/fake-network.d.ts +57 -0
  39. package/dist/bench/fake-network.js +169 -0
  40. package/dist/bench/index.d.ts +11 -0
  41. package/dist/bench/index.js +13 -0
  42. package/dist/bench/seeded.d.ts +11 -0
  43. package/dist/bench/seeded.js +37 -0
  44. package/dist/bench/settle.d.ts +2 -0
  45. package/dist/bench/settle.js +49 -0
  46. package/dist/bench/stewards.d.ts +17 -0
  47. package/dist/bench/stewards.js +20 -0
  48. package/dist/bodies/class-list.d.ts +14 -0
  49. package/dist/bodies/class-list.js +33 -0
  50. package/dist/bodies/joined-carry.d.ts +23 -0
  51. package/dist/bodies/joined-carry.js +42 -0
  52. package/dist/bodies/noble-crypto.d.ts +22 -0
  53. package/dist/bodies/noble-crypto.js +88 -0
  54. package/dist/bodies/seed-keys.d.ts +10 -0
  55. package/dist/bodies/seed-keys.js +42 -0
  56. package/dist/bodies/strict-tools.d.ts +10 -0
  57. package/dist/bodies/strict-tools.js +306 -0
  58. package/dist/bodies/web-carry.d.ts +65 -0
  59. package/dist/bodies/web-carry.js +224 -0
  60. package/dist/bodies/web-clock.d.ts +12 -0
  61. package/dist/bodies/web-clock.js +33 -0
  62. package/dist/browser/browser-ground.d.ts +69 -0
  63. package/dist/browser/browser-ground.js +229 -0
  64. package/dist/browser/index.d.ts +4 -0
  65. package/dist/browser/index.js +7 -0
  66. package/dist/browser/indexeddb-memory.d.ts +17 -0
  67. package/dist/browser/indexeddb-memory.js +97 -0
  68. package/dist/browser/locked-custody.d.ts +27 -0
  69. package/dist/browser/locked-custody.js +93 -0
  70. package/dist/browser/origin-classes.d.ts +7 -0
  71. package/dist/browser/origin-classes.js +31 -0
  72. package/dist/foundation.d.ts +150 -0
  73. package/dist/foundation.js +4 -0
  74. package/dist/ground/ground.d.ts +177 -0
  75. package/dist/ground/ground.js +363 -0
  76. package/dist/house/crossing.d.ts +37 -0
  77. package/dist/house/crossing.js +131 -0
  78. package/dist/house/house.d.ts +80 -0
  79. package/dist/house/house.js +1753 -0
  80. package/dist/house/rows-shape.d.ts +103 -0
  81. package/dist/house/rows-shape.js +12 -0
  82. package/dist/house/rows.d.ts +27 -0
  83. package/dist/house/rows.js +168 -0
  84. package/dist/index.d.ts +29 -1
  85. package/dist/index.js +25 -14
  86. package/dist/node/bridge.d.ts +17 -0
  87. package/dist/node/bridge.js +188 -0
  88. package/dist/node/cli.js +170 -0
  89. package/dist/node/custody.d.ts +20 -0
  90. package/dist/node/custody.js +34 -0
  91. package/dist/node/file-keys.d.ts +7 -0
  92. package/dist/node/file-keys.js +30 -0
  93. package/dist/node/file-memory.d.ts +13 -0
  94. package/dist/node/file-memory.js +91 -0
  95. package/dist/node/folder-classes.d.ts +5 -0
  96. package/dist/node/folder-classes.js +40 -0
  97. package/dist/node/gone.d.ts +2 -0
  98. package/dist/node/gone.js +7 -0
  99. package/dist/node/hand.d.ts +29 -0
  100. package/dist/node/hand.js +85 -0
  101. package/dist/node/held-keys.d.ts +14 -0
  102. package/dist/node/held-keys.js +36 -0
  103. package/dist/node/http.d.ts +11 -0
  104. package/dist/node/http.js +90 -0
  105. package/dist/node/index.d.ts +13 -0
  106. package/dist/node/index.js +15 -0
  107. package/dist/node/keychain-keys.d.ts +10 -0
  108. package/dist/node/keychain-keys.js +51 -0
  109. package/dist/node/ledger-memory.d.ts +17 -0
  110. package/dist/node/ledger-memory.js +151 -0
  111. package/dist/node/lock.d.ts +10 -0
  112. package/dist/node/lock.js +78 -0
  113. package/dist/node/node-ground.d.ts +33 -0
  114. package/dist/node/node-ground.js +147 -0
  115. package/dist/node/notify.d.ts +1 -0
  116. package/dist/node/notify.js +18 -0
  117. package/dist/node/tcp-carry.d.ts +39 -0
  118. package/dist/node/tcp-carry.js +216 -0
  119. package/dist/node/websocket.d.ts +6 -0
  120. package/dist/node/websocket.js +118 -0
  121. package/dist/quo/frame.d.ts +20 -0
  122. package/dist/quo/frame.js +48 -0
  123. package/dist/quo/room.d.ts +154 -0
  124. package/dist/quo/room.js +362 -0
  125. package/dist/serve/index.d.ts +27 -0
  126. package/dist/serve/index.js +55 -0
  127. package/package.json +40 -56
  128. package/dist/browser.d.ts +0 -1
  129. package/dist/browser.js +0 -8
  130. package/dist/cli.js +0 -16
  131. package/dist/core/being/being.d.ts +0 -17
  132. package/dist/core/being/being.js +0 -72
  133. package/dist/core/being/digest.d.ts +0 -3
  134. package/dist/core/being/digest.js +0 -17
  135. package/dist/core/being/faculty.d.ts +0 -10
  136. package/dist/core/being/faculty.js +0 -77
  137. package/dist/core/being/index.d.ts +0 -6
  138. package/dist/core/being/index.js +0 -8
  139. package/dist/core/being/kind.d.ts +0 -6
  140. package/dist/core/being/kind.js +0 -34
  141. package/dist/core/being/types.d.ts +0 -61
  142. package/dist/core/being/types.js +0 -4
  143. package/dist/core/being/words.d.ts +0 -13
  144. package/dist/core/being/words.js +0 -14
  145. package/dist/core/browser/index.d.ts +0 -37
  146. package/dist/core/browser/index.js +0 -196
  147. package/dist/core/browser/worker.d.ts +0 -11
  148. package/dist/core/browser/worker.js +0 -37
  149. package/dist/core/cli/command.d.ts +0 -13
  150. package/dist/core/cli/command.js +0 -330
  151. package/dist/core/cli/edge.d.ts +0 -7
  152. package/dist/core/cli/edge.js +0 -79
  153. package/dist/core/cli/harbor.d.ts +0 -25
  154. package/dist/core/cli/harbor.js +0 -115
  155. package/dist/core/contract/index.d.ts +0 -42
  156. package/dist/core/contract/index.js +0 -34
  157. package/dist/core/contract/link.d.ts +0 -4
  158. package/dist/core/contract/link.js +0 -45
  159. package/dist/core/crypto/aes.d.ts +0 -3
  160. package/dist/core/crypto/aes.js +0 -24
  161. package/dist/core/crypto/bytes.d.ts +0 -6
  162. package/dist/core/crypto/bytes.js +0 -33
  163. package/dist/core/crypto/ed25519.d.ts +0 -3
  164. package/dist/core/crypto/ed25519.js +0 -93
  165. package/dist/core/crypto/hash.d.ts +0 -2
  166. package/dist/core/crypto/hash.js +0 -11
  167. package/dist/core/crypto/index.d.ts +0 -7
  168. package/dist/core/crypto/index.js +0 -10
  169. package/dist/core/crypto/json.d.ts +0 -8
  170. package/dist/core/crypto/json.js +0 -250
  171. package/dist/core/crypto/mlkem.d.ts +0 -12
  172. package/dist/core/crypto/mlkem.js +0 -36
  173. package/dist/core/crypto/subtle.d.ts +0 -3
  174. package/dist/core/crypto/subtle.js +0 -11
  175. package/dist/core/crypto/x25519.d.ts +0 -2
  176. package/dist/core/crypto/x25519.js +0 -24
  177. package/dist/core/edge/index.d.ts +0 -164
  178. package/dist/core/edge/index.js +0 -739
  179. package/dist/core/edge/kit.d.ts +0 -2
  180. package/dist/core/edge/kit.js +0 -2
  181. package/dist/core/folder/index.d.ts +0 -18
  182. package/dist/core/folder/index.js +0 -130
  183. package/dist/core/git/http.d.ts +0 -6
  184. package/dist/core/git/http.js +0 -102
  185. package/dist/core/git/index.d.ts +0 -5
  186. package/dist/core/git/index.js +0 -10
  187. package/dist/core/git/object.d.ts +0 -40
  188. package/dist/core/git/object.js +0 -103
  189. package/dist/core/git/pack.d.ts +0 -9
  190. package/dist/core/git/pack.js +0 -171
  191. package/dist/core/git/store.d.ts +0 -23
  192. package/dist/core/git/store.js +0 -120
  193. package/dist/core/git/zlib.d.ts +0 -6
  194. package/dist/core/git/zlib.js +0 -210
  195. package/dist/core/harbor/carrying.d.ts +0 -50
  196. package/dist/core/harbor/carrying.js +0 -66
  197. package/dist/core/harbor/catalogue.d.ts +0 -33
  198. package/dist/core/harbor/catalogue.js +0 -365
  199. package/dist/core/harbor/dna.d.ts +0 -13
  200. package/dist/core/harbor/dna.js +0 -120
  201. package/dist/core/harbor/dock.d.ts +0 -62
  202. package/dist/core/harbor/dock.js +0 -381
  203. package/dist/core/harbor/harbor.d.ts +0 -16
  204. package/dist/core/harbor/harbor.js +0 -448
  205. package/dist/core/harbor/index.d.ts +0 -11
  206. package/dist/core/harbor/index.js +0 -14
  207. package/dist/core/harbor/memory.d.ts +0 -10
  208. package/dist/core/harbor/memory.js +0 -25
  209. package/dist/core/harbor/package.d.ts +0 -20
  210. package/dist/core/harbor/package.js +0 -172
  211. package/dist/core/harbor/probe.d.ts +0 -22
  212. package/dist/core/harbor/probe.js +0 -15
  213. package/dist/core/harbor/registry.d.ts +0 -15
  214. package/dist/core/harbor/registry.js +0 -110
  215. package/dist/core/harbor/root-line.d.ts +0 -7
  216. package/dist/core/harbor/root-line.js +0 -9
  217. package/dist/core/harbor/terrain.d.ts +0 -25
  218. package/dist/core/harbor/terrain.js +0 -28
  219. package/dist/core/http/index.d.ts +0 -2
  220. package/dist/core/http/index.js +0 -154
  221. package/dist/core/http/websocket.d.ts +0 -29
  222. package/dist/core/http/websocket.js +0 -133
  223. package/dist/core/line/answer.d.ts +0 -8
  224. package/dist/core/line/answer.js +0 -60
  225. package/dist/core/line/frame.d.ts +0 -29
  226. package/dist/core/line/frame.js +0 -77
  227. package/dist/core/line/ground.d.ts +0 -3
  228. package/dist/core/line/ground.js +0 -7
  229. package/dist/core/line/index.d.ts +0 -4
  230. package/dist/core/line/index.js +0 -8
  231. package/dist/core/line/web.d.ts +0 -12
  232. package/dist/core/line/web.js +0 -117
  233. package/dist/core/node/index.d.ts +0 -23
  234. package/dist/core/node/index.js +0 -124
  235. package/dist/core/pointer/bodies.d.ts +0 -31
  236. package/dist/core/pointer/bodies.js +0 -118
  237. package/dist/core/pointer/index.d.ts +0 -2
  238. package/dist/core/pointer/index.js +0 -4
  239. package/dist/core/pointer/world.d.ts +0 -45
  240. package/dist/core/pointer/world.js +0 -106
  241. package/dist/core/proof/contracts.d.ts +0 -19
  242. package/dist/core/proof/contracts.js +0 -116
  243. package/dist/core/proof/expect.d.ts +0 -6
  244. package/dist/core/proof/expect.js +0 -18
  245. package/dist/core/proof/index.d.ts +0 -3
  246. package/dist/core/proof/index.js +0 -14
  247. package/dist/core/proof/law.d.ts +0 -25
  248. package/dist/core/proof/law.js +0 -715
  249. package/dist/core/quo/address.d.ts +0 -19
  250. package/dist/core/quo/address.js +0 -84
  251. package/dist/core/quo/door.d.ts +0 -34
  252. package/dist/core/quo/door.js +0 -174
  253. package/dist/core/quo/index.d.ts +0 -9
  254. package/dist/core/quo/index.js +0 -12
  255. package/dist/core/quo/invitation.d.ts +0 -8
  256. package/dist/core/quo/invitation.js +0 -19
  257. package/dist/core/quo/keys.d.ts +0 -40
  258. package/dist/core/quo/keys.js +0 -79
  259. package/dist/core/quo/payload.d.ts +0 -15
  260. package/dist/core/quo/payload.js +0 -55
  261. package/dist/core/quo/relations.d.ts +0 -40
  262. package/dist/core/quo/relations.js +0 -33
  263. package/dist/core/quo/reply.d.ts +0 -13
  264. package/dist/core/quo/reply.js +0 -35
  265. package/dist/core/quo/seal.d.ts +0 -42
  266. package/dist/core/quo/seal.js +0 -78
  267. package/dist/core/quo/standing.d.ts +0 -39
  268. package/dist/core/quo/standing.js +0 -90
  269. package/dist/core/tcp/index.d.ts +0 -27
  270. package/dist/core/tcp/index.js +0 -209
  271. package/dist/core/ward/allowance.d.ts +0 -14
  272. package/dist/core/ward/allowance.js +0 -32
  273. package/dist/core/ward/cells.d.ts +0 -7
  274. package/dist/core/ward/cells.js +0 -74
  275. package/dist/core/ward/house.d.ts +0 -70
  276. package/dist/core/ward/house.js +0 -499
  277. package/dist/core/ward/index.d.ts +0 -5
  278. package/dist/core/ward/index.js +0 -7
  279. package/dist/core/ward/partition.d.ts +0 -51
  280. package/dist/core/ward/partition.js +0 -66
  281. package/dist/core/ward/stance.d.ts +0 -31
  282. package/dist/core/ward/stance.js +0 -193
  283. package/dist/core/ward/ward.d.ts +0 -44
  284. package/dist/core/ward/ward.js +0 -140
  285. package/dist/core.d.ts +0 -10
  286. package/dist/core.js +0 -19
  287. package/dist/defaults/dock/index.d.ts +0 -4
  288. package/dist/defaults/dock/index.js +0 -11
  289. package/dist/defaults/index.d.ts +0 -5
  290. package/dist/defaults/index.js +0 -10
  291. package/dist/defaults/memory/index.d.ts +0 -12
  292. package/dist/defaults/memory/index.js +0 -39
  293. package/dist/defaults/tcp/index.d.ts +0 -16
  294. package/dist/defaults/tcp/index.js +0 -82
  295. package/dist/defaults/ward/index.d.ts +0 -4
  296. package/dist/defaults/ward/index.js +0 -11
  297. package/dist/defaults/web/index.d.ts +0 -15
  298. package/dist/defaults/web/index.js +0 -90
  299. package/dist/edge.d.ts +0 -1
  300. package/dist/edge.js +0 -9
  301. package/dist/kit.d.ts +0 -4
  302. package/dist/kit.js +0 -12
  303. package/dist/node.d.ts +0 -1
  304. package/dist/node.js +0 -8
  305. package/src/browser.ts +0 -10
  306. package/src/cli.ts +0 -15
  307. package/src/core/being/being.ts +0 -84
  308. package/src/core/being/digest.ts +0 -18
  309. package/src/core/being/faculty.ts +0 -76
  310. package/src/core/being/index.ts +0 -8
  311. package/src/core/being/kind.ts +0 -37
  312. package/src/core/being/types.ts +0 -74
  313. package/src/core/being/words.ts +0 -31
  314. package/src/core/browser/index.ts +0 -219
  315. package/src/core/browser/worker.ts +0 -63
  316. package/src/core/cli/command.ts +0 -311
  317. package/src/core/cli/edge.ts +0 -86
  318. package/src/core/cli/harbor.ts +0 -120
  319. package/src/core/contract/index.ts +0 -82
  320. package/src/core/contract/link.ts +0 -58
  321. package/src/core/crypto/aes.ts +0 -26
  322. package/src/core/crypto/bytes.ts +0 -37
  323. package/src/core/crypto/ed25519.ts +0 -92
  324. package/src/core/crypto/hash.ts +0 -14
  325. package/src/core/crypto/index.ts +0 -10
  326. package/src/core/crypto/json.ts +0 -241
  327. package/src/core/crypto/mlkem.ts +0 -38
  328. package/src/core/crypto/subtle.ts +0 -13
  329. package/src/core/crypto/x25519.ts +0 -23
  330. package/src/core/edge/index.ts +0 -865
  331. package/src/core/folder/index.ts +0 -137
  332. package/src/core/git/http.ts +0 -103
  333. package/src/core/git/index.ts +0 -10
  334. package/src/core/git/object.ts +0 -116
  335. package/src/core/git/pack.ts +0 -147
  336. package/src/core/git/store.ts +0 -122
  337. package/src/core/git/zlib.ts +0 -197
  338. package/src/core/harbor/carrying.ts +0 -121
  339. package/src/core/harbor/catalogue.ts +0 -386
  340. package/src/core/harbor/dna.ts +0 -116
  341. package/src/core/harbor/dock.ts +0 -420
  342. package/src/core/harbor/harbor.ts +0 -441
  343. package/src/core/harbor/index.ts +0 -14
  344. package/src/core/harbor/memory.ts +0 -31
  345. package/src/core/harbor/package.ts +0 -195
  346. package/src/core/harbor/probe.ts +0 -39
  347. package/src/core/harbor/registry.ts +0 -107
  348. package/src/core/harbor/root-line.ts +0 -19
  349. package/src/core/harbor/terrain.ts +0 -54
  350. package/src/core/http/index.ts +0 -147
  351. package/src/core/http/websocket.ts +0 -124
  352. package/src/core/line/answer.ts +0 -60
  353. package/src/core/line/frame.ts +0 -83
  354. package/src/core/line/ground.ts +0 -18
  355. package/src/core/line/index.ts +0 -8
  356. package/src/core/line/web.ts +0 -123
  357. package/src/core/node/index.ts +0 -139
  358. package/src/core/pointer/bodies.ts +0 -122
  359. package/src/core/pointer/index.ts +0 -4
  360. package/src/core/pointer/world.ts +0 -134
  361. package/src/core/proof/contracts.ts +0 -134
  362. package/src/core/proof/expect.ts +0 -25
  363. package/src/core/proof/index.ts +0 -14
  364. package/src/core/proof/law.ts +0 -742
  365. package/src/core/quo/address.ts +0 -87
  366. package/src/core/quo/door.ts +0 -180
  367. package/src/core/quo/index.ts +0 -12
  368. package/src/core/quo/invitation.ts +0 -19
  369. package/src/core/quo/keys.ts +0 -91
  370. package/src/core/quo/payload.ts +0 -61
  371. package/src/core/quo/relations.ts +0 -62
  372. package/src/core/quo/reply.ts +0 -38
  373. package/src/core/quo/seal.ts +0 -101
  374. package/src/core/quo/standing.ts +0 -111
  375. package/src/core/stand/main.ts +0 -20
  376. package/src/core/stand/stand.ts +0 -259
  377. package/src/core/tcp/index.ts +0 -227
  378. package/src/core/ward/allowance.ts +0 -47
  379. package/src/core/ward/cells.ts +0 -77
  380. package/src/core/ward/house.ts +0 -550
  381. package/src/core/ward/index.ts +0 -7
  382. package/src/core/ward/partition.ts +0 -120
  383. package/src/core/ward/stance.ts +0 -215
  384. package/src/core/ward/ward.ts +0 -166
  385. package/src/core.ts +0 -55
  386. package/src/defaults/dock/index.ts +0 -12
  387. package/src/defaults/index.ts +0 -10
  388. package/src/defaults/memory/index.ts +0 -50
  389. package/src/defaults/tcp/index.ts +0 -89
  390. package/src/defaults/ward/index.ts +0 -12
  391. package/src/defaults/web/index.ts +0 -97
  392. package/src/edge.ts +0 -11
  393. package/src/index.ts +0 -18
  394. package/src/kit.ts +0 -15
  395. package/src/node.ts +0 -10
  396. /package/dist/{cli.d.ts → node/cli.d.ts} +0 -0
package/README.md CHANGED
@@ -1,461 +1,158 @@
1
1
  # nervur
2
2
 
3
- Nervur's kit of [Quo](https://quo.systems). Quo is a protocol: an object
4
- asks another object and gets an answer, without knowing where it is. This
5
- package is one implementation of it, and the two names never stand for
6
- the same thing. Where they disagree, Quo's spec wins.
7
-
8
- You write classes, beings and faculties, and nothing else. A harbor
9
- unpacks a whole world from them.
10
-
11
- ## Install
12
-
13
- ```sh
14
- npm install nervur
15
- ```
16
-
17
- Node 22.18 or later. The main entry imports no platform, so it runs in a
18
- browser, Deno, Bun and workerd as well. `nervur/folder` keeps a harbor on
19
- a disk and needs Node's file system.
20
-
21
- ## A harbor where you run
22
-
23
- ```js
24
- import { readFile } from 'node:fs/promises';
25
- import { Harbor } from 'nervur';
26
-
27
- const harbor = await Harbor.open();
28
- await harbor.ask({ method: 'stand' });
29
- const source = await readFile('./greetings.js', 'utf8');
30
- await harbor.ask({ method: 'ask', args: { being: 'catalogue', method: 'add', args: { source } } });
31
- ```
32
-
33
- A harbor is asked and nothing else. `harbor.ask` takes one root request,
34
- `{ ward?, method?, args? }`, asks the box ward, or the hosted ward named,
35
- as its root, and answers one plain JSON value. `arrive`, `holds` and
36
- `close` are the rest of what a program holds of a harbor.
37
-
38
- With no terrain, the harbor picks its ground's bodies itself. In Node it
39
- keeps itself in a folder, `where` if you name one, else `$NERVUR_DIR`,
40
- else `~/.nervur`, speaks TCP and the web where you open them,
41
- and serves its root line, so the `nervur` command below asks it while it
42
- stands. A folder opens in one run at a time. Bundled for a browser, in a
43
- page or a worker, it keeps itself in the IndexedDB database `where`
44
- names, else `nervur`, its seed sealed under a key the browser never hands
45
- out, speaks the web where you open it, and opens in one run at a time.
46
- On Cloudflare Workers it is one Durable Object of many a worker carries,
47
- running in a child worker the object loads for the commit `live` names,
48
- answering Quo at `/<name>/quo` on whatever host reaches it, and asking
49
- over TCP and the web. Anywhere else it lives as long as its process and
50
- speaks the web where you open it. Hand in a terrain, as below, and that
51
- one is used.
52
-
53
- Nothing enters a harbor unasked. A new harbor holds its catalogue alone,
54
- and a carrier stands only once the root opens it:
55
-
56
- ```js
57
- await harbor.ask({ method: 'open', args: { key: 'web', class: 'org.nervur.web' } });
3
+ `nervur` is a library for writing beings and opening the house that holds
4
+ them. It is the first kit of [Quo](https://quo.systems), a protocol where
5
+ a door is one function: bytes in, bytes or nothing out.
6
+
7
+ This version is a prerelease, and the API moves until 1.0.0. Install it
8
+ with `npm i nervur@next`. It runs on Node 22.18 or later.
9
+ [AUTHORING.md](AUTHORING.md) teaches beings, faculties and grounds.
10
+ [KIT-SPEC.md](KIT-SPEC.md) answers every choice Quo leaves to a kit.
11
+
12
+ ## Words
13
+
14
+ A **being** is an instance of a class you write. She keeps **cells**,
15
+ which are JSON values, and answers **asks**, which are the methods others
16
+ may call. The **house** holds beings, keeps their cells, and seals every
17
+ ask that crosses its door. A **ground** is the process houses run in. It
18
+ hands each house a seed, somewhere to keep rows, its classes, a way to
19
+ carry bytes, and the **faculties** its beings may call.
20
+
21
+ ## A being
22
+
23
+ Every ask declares its arguments and its result, and may carry examples.
24
+ The house refuses arguments that do not match.
25
+
26
+ ```ts
27
+ // greeter.ts
28
+ import { Being, s, type Args } from 'nervur/being';
29
+
30
+ export class Greeter extends Being.of({
31
+ kind: 'org.example.greeter',
32
+ description: 'Greets whoever asks, and counts them.',
33
+ cells: { greeted: 0 },
34
+ asks: {
35
+ hello: {
36
+ args: s.object({ name: s.string() }),
37
+ result: s.string(),
38
+ examples: [{ cells: { greeted: 2 }, args: { name: 'Ada' }, gives: { result: 'Hello, Ada. You are number 3.' } }],
39
+ },
40
+ },
41
+ }) {
42
+ hello({ name }: Args<Greeter, 'hello'>) {
43
+ this.cells.greeted += 1;
44
+ return `Hello, ${name}. You are number ${this.cells.greeted}.`;
45
+ }
46
+ }
58
47
  ```
59
48
 
60
- ## A harbor on the edge
61
-
62
- An edge harbor is born on your machine and carried there, so you pilot it
63
- from your own harbor, as you pilot one on a server, and you move its code
64
- the same way, with no deploy. One worker carries as many harbors as you
65
- pack into it, each a Durable Object by its name, answering at
66
- `/<name>/quo`. The worker is a shell: it keeps each harbor's storage and
67
- its web door, and runs the harbor, the kit and the modules its `live`
68
- commit holds, in a child worker Cloudflare's Worker Loader makes of them.
69
- The worker is a folder of its own, an ES module project (`"type":
70
- "module"` in its `package.json`), holding the worker and its
71
- `wrangler.toml`:
72
-
73
- ```js
74
- // worker.js
75
- import { harborShell, harborWorker } from 'nervur/edge';
76
- import kit from 'nervur/edge/kit';
77
- import pack from './pack.edge.json';
78
-
79
- export const Harbor = harborShell({ kit, pack });
80
- export default harborWorker();
49
+ ## A test
50
+
51
+ The bench opens two houses in one process, so every ask crosses a door
52
+ as it would in production. `Bench.check` runs every example twice and
53
+ describes every state to every role.
54
+
55
+ ```ts
56
+ // greeter.test.ts
57
+ import assert from 'node:assert/strict';
58
+ import { test } from 'node:test';
59
+ import { Bench } from 'nervur/bench';
60
+ import { Greeter } from './greeter.ts';
61
+
62
+ test('Greeter keeps her examples and her table', async () => {
63
+ await Bench.check(Greeter);
64
+ });
65
+
66
+ test('Greeter counts whoever she greets', async () => {
67
+ const bench = await Bench.open({ classes: [Greeter] });
68
+ const greeter = await bench.place(Greeter);
69
+ assert.deepEqual(await greeter.ask('hello', { name: 'Ada' }), { result: 'Hello, Ada. You are number 1.' });
70
+ assert.deepEqual(await greeter.cells(), { greeted: 1 });
71
+ });
81
72
  ```
82
73
 
83
- ```toml
84
- # wrangler.toml
85
- name = "harbor"
86
- main = "worker.js"
87
- compatibility_date = "2026-09-01"
88
-
89
- [[durable_objects.bindings]]
90
- name = "HARBOR"
91
- class_name = "Harbor"
74
+ ## A ground
92
75
 
93
- [[migrations]]
94
- tag = "v1"
95
- new_sqlite_classes = ["Harbor"]
76
+ A ground is the process houses run in, and you write none. `nervur up`
77
+ runs one on a folder. Each house's code is a folder of its own, whose
78
+ index names its steward. Here the greeter is the steward.
96
79
 
97
- [[worker_loaders]]
98
- binding = "LOADER"
80
+ ```ts
81
+ // house/index.ts
82
+ export { Greeter as steward } from '../greeter.ts';
99
83
  ```
100
84
 
101
- The Worker Loader is in beta, and on Cloudflare it needs the Workers Paid
102
- plan. `wrangler dev` runs it on your machine at no cost.
85
+ Run the ground in the folder, and leave it running.
103
86
 
104
- Make the harbor and set it up with the command, from that folder, naming
105
- where the edge will reach it:
106
-
107
- ```sh
108
- nervur init --dir ./harbor
109
- nervur module add ./greetings.js --dir ./harbor
110
- nervur reach http://127.0.0.1:8787/main/quo --dir ./harbor
111
- nervur own me --dir ./harbor
87
+ ```bash
88
+ npx nervur up .
112
89
  ```
113
90
 
114
- `own` prints the owner invitation, which never leaves your machine. Run
115
- it on this machine first:
91
+ In a second shell, add the house once. The ground keeps it in its record,
92
+ and opens it again at every start.
116
93
 
117
- ```sh
118
- nervur edge dev ./pack.edge.json main --dir ./harbor
94
+ ```bash
95
+ npx nervur houses add name=main memory='{"body":"ledger"}' classes='{"body":"folder","at":"house"}'
119
96
  ```
120
97
 
121
- `edge dev` packs the harbor as `main` into `pack.edge.json`, beside any
122
- harbor packed there before, and runs your `wrangler dev`, keeping the
123
- objects' storage and a secret of its own in `.nervur-edge`, so the
124
- harbor stands again each time you run it. The harbor's code travels in
125
- its package, as its DNA. The first time its object starts, the harbor
126
- lands in its storage; after that the storage is the harbor, and a new
127
- deploy leaves it be. Then, from your own harbor:
128
-
129
- ```sh
130
- nervur pilot edge '<the owner invitation>' --dir ./mine
131
- nervur host shop --via edge --dir ./mine
132
- nervur module add ./greetings.js --via edge --dir ./mine
133
- ```
134
-
135
- A module added, or `live` moved back, runs on the edge at once: the
136
- worker loads the next child for the commit `live` names, with no deploy.
137
- A module that does not load there is refused with its reason, and `live`
138
- stays where it was.
139
-
140
- For Cloudflare, keep one secret for the worker, `wrangler secret put
141
- NERVUR_SECRET`, and hold the same one as `NERVUR_SECRET` in your shell.
142
- Name each harbor's address with `reach`, pack each with
143
- `nervur edge pack ./pack.edge.json <name> --dir <its folder>`, and
144
- `wrangler deploy`. A pack holds every seed sealed under that secret, so
145
- it ships in the bundle and opens nowhere else, and a new harbor is a new
146
- deploy, never a new secret. `pilot` opens the web carrier where the
147
- invitation names a web address. A name the pack does not hold answers
148
- 404, so a stranger's request mints nothing.
149
-
150
- ## A world in one process
151
-
152
- A module is one file of JavaScript that imports nothing but `nervur`:
98
+ Then ask the steward through the ground's hand.
153
99
 
154
- ```js
155
- // greetings.js
156
- import { Being, Faculty } from 'nervur';
157
-
158
- // Its name, as a kind is named, and its version.
159
- export const module = 'org.example.greetings';
160
- export const version = '1.0.0';
161
-
162
- // A contract, and a faculty that fulfils it. Every class names its kind.
163
- class Clock extends Faculty {
164
- static kind = 'org.example.clock';
165
- }
166
- class SystemTime extends Clock {
167
- static kind = 'org.example.system-time';
168
- static asks = { now: {} };
169
- now() {
170
- return { now: Date.now() };
171
- }
172
- }
173
-
174
- // A being, who lends a clock by its contract.
175
- class Greeter extends Being {
176
- static kind = 'org.example.greeter';
177
- static asks = { hello: {} };
178
- async hello(args, asker) {
179
- if (!this.stance.standings.get('clock')) await this.stance.lend(Clock, 'clock');
180
- const time = await this.stance.standings.get('clock')?.ask('now');
181
- return { hello: asker.id ?? 'stranger', time };
182
- }
183
- }
184
-
185
- export const classes = [SystemTime, Greeter];
100
+ ```bash
101
+ npx nervur ask main hello name=Ada
186
102
  ```
187
103
 
188
- A harbor's catalogue takes its source, commits it, and runs it:
104
+ Each ask greets Ada once more, since the count lands in the house's
105
+ ledger before the answer, and it outlives a restart. The ground keeps
106
+ the house's seed, its ledger and its record in `state/`, readable by
107
+ you alone. Keep that folder secret: a house opens on no other seed.
108
+ `npx nervur help` lists everything the ground offers.
189
109
 
190
- ```js
191
- import { readFile } from 'node:fs/promises';
192
- import { DEFAULTS, World } from 'nervur';
110
+ ## A ground in a page
193
111
 
194
- const world = new World(DEFAULTS);
195
- const harbor = await world.harbor('home');
196
- const source = await readFile('./greetings.js', 'utf8');
197
- await harbor.ask({ method: 'ask', args: { being: 'catalogue', method: 'add', args: { source } } });
198
- await harbor.ask({ method: 'open', args: { key: 'clock', class: 'org.example.system-time' } });
199
- await harbor.ask({ method: 'host', args: { ward: 'alice' } });
200
- await harbor.ask({ ward: 'alice', method: 'boot', args: { key: 'greeter', class: 'org.example.greeter' } });
201
- ```
112
+ The same house runs in a browser. Bundle the house's module and serve it
113
+ on your origin, beside a page that opens the ground.
202
114
 
203
- A second harbor in the same world takes an invitation on the greeter and
204
- asks it through the world, sealed as Quo's bytes. `world.restart('home')`
205
- opens the harbor again from what its memory kept.
206
-
207
- ## Kinds
208
-
209
- A row keeps the kind of the class a being is born of, and a being lends
210
- by a contract's kind. A kind is declared on the class, because a bundler
211
- renames classes. It is a domain you own, reversed, then a name, as Apple
212
- and Matrix name things: `com.acme.shop`. Every segment is lowercase
213
- letters, digits and `-`, and there are three at least. Each class
214
- declares its own: a subclass that stands, and every contract between a
215
- faculty and `Faculty`. `org.nervur.` is the kit's, and `org.example.` is
216
- for examples like the one above. A module's classes stand under its own
217
- domain: `com.acme.shop` stands `com.acme.*` kinds. A harbor refuses a
218
- module in which one kind names two classes or two contracts, or names a
219
- class and a contract.
220
-
221
- ## The DNA
222
-
223
- Your classes come in modules, each one file exporting `module`, `version`
224
- and `classes`, a module named as a kind is. A harbor's catalogue keeps
225
- its code as a git repository, its DNA, from its first moment: a commit
226
- holds `modules/<module>.js` for every module the harbor runs, and `live`
227
- names the commit that stands. Her asks, the root's and an owner's:
228
-
229
- - `add { source, name? }` commits a module's source on `live` and moves
230
- `live` to it; the same module again takes its new version.
231
- - `remove { module }` commits its file away, refused while a being or a
232
- ward stands on its kinds.
233
- - `live { commit? }` moves `live` to a commit or a fetched ref, or, with
234
- none, names the commit that stands. Moving `live` back is a rollback.
235
- - `log` walks back from `live`. `modules` shows what `live` runs, and why
236
- a module does not.
237
- - `origin { url }` names a git repository over HTTP, and `fetch` reads
238
- every ref it has and all they reach into the harbor, touching nothing
239
- there.
240
-
241
- Moving `live` runs the commit's modules together, or refuses them with
242
- the reason and leaves `live` where it was. Once they run, every being a
243
- new class resolves is born again of it, on the cells she keeps. A
244
- restart stands `live` from what the harbor keeps, with no network. The
245
- objects live in the harbor's memory, sealed as everything else is, so a
246
- harbor carried to another ground carries its DNA. Real `git` reads a
247
- harbor's objects, and a harbor reads what `git` serves.
248
-
249
- ## The onion
250
-
251
- A harbor is one package. Only the seed and the terrain's bodies, its
252
- loader among them, stand outside it. It stands in three levels, and each
253
- level stands the next and leaves it alone.
254
-
255
- 1. **The boot**, the harbor's own, from the library's core alone. The
256
- terrain gives the seed, which opens its memory; the terrain keeps that
257
- memory as sealed bytes and reads none of it. The box ward unpacks, the
258
- catalogue stands and runs every module `live` holds, every registry the
259
- catalogue resolves stands, and then the dock, of her class. The door is
260
- hers from here, and `Harbor.open()` returns. It is one call, and no ask
261
- makes it.
262
- 2. **The dock's**, on her `stand` ask. She stands every other faculty,
263
- registries first, then memory faculties, then the rest; hands her
264
- routes to the carrier; and stands every ward she hosts, under the seed
265
- she keeps for it.
266
- 3. **Each ward's beings**, stood by nothing. A being's cells, occupants
267
- and standings are her ward's rows, so she is born from her row when an
268
- ask reaches her, once for the asks in flight on her, and dropped after.
269
- A harbor holds in memory its faculties, its wards and the beings
270
- answering now.
271
-
272
- After the boot a harbor takes asks alone. Whoever holds it asks `stand`:
273
-
274
- ```js
275
- const harbor = await Harbor.open();
276
- await harbor.ask({ method: 'stand' });
277
- ```
115
+ ```ts
116
+ // page.ts
117
+ import { BrowserGround } from 'nervur/browser';
278
118
 
279
- `stand` answers what stood, or silence where everything already stands.
280
- The command asks it of every harbor it opens.
281
-
282
- Cells decide what stands. The modules only resolve a kind a row keeps.
283
- Opening a harbor on empty memory is its genesis: the harbor writes the
284
- catalogue and the default dock, and the root's asks write the rest: `add`
285
- on the catalogue, `open`, `host`, `route`, and `boot` on a ward.
286
- `host { ward, seed? }` stands a ward under a seed you name, or a drawn
287
- one.
288
-
289
- A ward is a being too, and her row keeps her class's kind. `Ward` and
290
- `Dock` are contracts, and `DefaultWard` and `DefaultDock` the library's
291
- defaults of them. A class of yours extending either, in a module the
292
- catalogue runs, is a ward of your own: `host { ward, class }` stands a
293
- hosted ward of it, and `become { class }` on any ward, the box ward's
294
- dock among them, has her born again of it on the same cells and
295
- relations. A dock of yours stands on every open, since she stands once
296
- the catalogue runs.
297
-
298
- Every class comes from a registry. The catalogue is the library's, and a
299
- class of yours extending `RegistryFaculty` is another: open it as any
300
- faculty, and name it where a class is named. `open { key, class,
301
- registry }` stands a faculty through it, `host { ward, registry }` stands
302
- a ward and every class of it through it, and `become { class, registry }`
303
- stands the dock through it, where the catalogue stands that registry. A
304
- registry may stand through another.
305
-
306
- A ward's place is kept by the root memory unless you name a memory
307
- faculty. `open { key: 'vault', class: 'org.nervur.ground-memory' }` opens
308
- the memory faculty every ground ships, and `host { ward, memory: 'vault' }`
309
- keeps the ward there. A class of yours extending `MemoryFaculty` keeps a
310
- ward in a bucket or a database the same way, and `move { ward, memory }`
311
- carries a ward between keepers whole.
312
-
313
- ## What it holds
314
-
315
- - **Being, Faculty, Ward, Dock.** What you extend, each a contract.
316
- A faculty's contract is its class and every class between it and
317
- `Faculty`. `DefaultWard` and `DefaultDock` are the kit's ward and dock.
318
- - **Entropy, Clock, Custody, Memory, Carrier, Loader.** The contracts a
319
- terrain fulfils. Each has one suite, and every body that fulfils it
320
- passes it. `nervur/proof` hands you those suites and the unpacking
321
- law's as scenes, a title and a function each, so a body of your own,
322
- a memory in a cloud or a secret of your platform's, runs them under
323
- your own runner: `for (const [title, scene] of memoryScenes('Mine',
324
- make, expect)) test(title, scene)`.
325
- - **Harbor, Terrain, Catalogue, Registry.** The onion.
326
- - **World, PointerTerrain** and the pointer bodies. A whole world with
327
- this package alone.
328
- - **SourceLoader, BundleLoader.** A module's source run by the engine's
329
- own import, its `nervur` linked to the kit running, and the modules a
330
- bundle carries, found by their git blob, for a service worker, which
331
- imports nothing once it runs.
332
- - **addGround, grounds**: the grounds `Harbor.open()` tries, and a way to
333
- add your own.
334
- - **NodeTerrain**, from `nervur/node`: the Node ground's terrain, for a
335
- folder you name in code.
336
- - **BrowserTerrain, IdbMemory, IdbCustody**, from `nervur/browser`: the
337
- browser ground's terrain and bodies. `serveWorker(Harbor.open())` at
338
- the top of a shared or service worker holds one harbor for every tab,
339
- each tab asks it with `rootOf(worker)`, and a push the service worker
340
- hears is the dock's `heard`, told to every carrier.
341
- - **harborShell, harborWorker, EdgeMemory, EdgeCustody, EdgeLoader**,
342
- from `nervur/edge`, and the kit as one module's text, from
343
- `nervur/edge/kit`: the edge's shell and the bodies its children stand
344
- on.
345
- - **FolderMemory, FolderCustody**, from `nervur/folder`.
346
- - **TcpCarrier, TcpListener, NodeSockets**, from `nervur/tcp`: Quo over
347
- TCP. Route a ward pk to its `tcp://host:port` addresses on the carrier,
348
- hand the listener your harbor, and harbors in two processes, or a
349
- harbor and another kit, speak. `TcpFaculty` is the same carrier as a
350
- faculty of a harbor, on the sockets its terrain hands it:
351
- `NodeSockets` on Node, a worker's own on the edge.
352
- - **WebDialer, WebFaculty**: Quo over the web, a post to `https://` or a
353
- held line to `wss://`, in any engine with `fetch` and WebSocket.
354
- `webServe`, from `nervur/http`, is the listener a Node terrain hands
355
- the web carrier. `answerPost(harbor, listen, request)` answers one post
356
- and nothing more, for a function that opens a harbor per request and
357
- closes it.
358
- - **DEFAULTS**: the one list of beings and faculties every ground runs
359
- where you write none, handed to a terrain as `defaults`.
360
- - **CarrierFaculty**: a carrier of your own. It says which addresses it
361
- accepts, dials them, and says the carrier of Quo it `carries`, `tcp`
362
- or `web`, so the command finds it. One that answers `relay` for a ward
363
- pk no door holds is handed that pk's boxes, and every carrier hears
364
- the dock's `heard` when a device hears a push.
365
-
366
- Quo crosses two carriers, TCP and the web, and no third. MCP, an HTTP API
367
- and every other outside protocol are gateway faculties: classes that
368
- serve their clients, a UI in a browser, an MCP client, a caller holding
369
- a bearer token, on one side, and stand as an ordinary being on the
370
- other, offering standings, holding occupants and speaking Quo inbound
371
- and outbound. They and every screen
372
- are classes written over this package, and none ships in it.
373
-
374
- ## The command
375
-
376
- `nervur` stands a harbor on this machine: its seed and sealed memory in a
377
- folder, Quo over TCP as its carrier. A module is a file that exports
378
- `module`, `version` and `classes`.
379
-
380
- ```sh
381
- nervur init --dir ./harbor
382
- nervur module add ./greetings.js --dir ./harbor
383
- nervur serve --dir ./harbor --port 7000
384
- nervur reach tcp://harbor.example:7000 --dir ./harbor
385
- nervur open web org.nervur.web --dir ./harbor
386
- nervur ask web listen '{"port":8080,"path":"/quo"}' --dir ./harbor
387
- nervur host alice --dir ./harbor
388
- nervur boot --ward alice greeter org.example.greeter --dir ./harbor
389
- nervur ask --ward alice greeter hello --dir ./harbor
390
- ```
391
-
392
- `reach` names where the harbor is reached, and every invitation it gives
393
- carries those addresses in `at`. With no `reach`, an invitation carries
394
- where the harbor listens, which serves a harbor callers reach directly;
395
- behind a router or a proxy, name the public address with `reach`. A
396
- harbor that takes such an invitation keeps them as that ward's route,
397
- so nobody routes it by hand. Where an invitation carries no `at`,
398
- `nervur route <ward pk> tcp://host:port` names the route, and a route
399
- named this way is trusted first.
400
-
401
- `init` makes the harbor, opens its TCP carrier unless you pass
402
- `--no-tcp`, and prints its pk and an owner invitation. `serve` listens for
403
- Quo on that carrier and for the root's asks on a local socket, open to
404
- you alone, and adds nothing to the harbor: one with no TCP carrier is not
405
- served. Every other command is one root ask, `pilot` at most two, sent
406
- to the served harbor, or answered from the folder when none is served.
407
- Each prints one JSON line. `--dir` defaults to `$NERVUR_DIR`, then `~/.nervur`.
408
- `module add` reads the file and commits its text into the harbor's DNA,
409
- so the harbor holds its own code on any ground. Routes live in the
410
- harbor like everything else, so a restart finds both. `nervur modules`
411
- shows what runs, `nervur module remove <module>` stops one, `nervur log`
412
- walks the commits, `nervur live <commit>` moves `live`, and `nervur
413
- origin <url>` with `nervur fetch` reads a git repository into the
414
- harbor.
415
-
416
- A harbor elsewhere is piloted with the owner invitation its `init`
417
- printed, from a harbor of your own:
418
-
419
- ```sh
420
- nervur pilot far '<owner invitation>' --dir ./mine
421
- nervur host shop --via far --dir ./mine
422
- ```
119
+ // Every tab of this origin joins one ground, and the tab holding its lock runs it.
120
+ const ground = await BrowserGround.open();
423
121
 
424
- `pilot` is your dock's `hold`: it keeps the invitation under the name
425
- `far` as an ordinary Quo relation, kept in your harbor's memory, and
426
- reaches the far harbor where its invitation's `at` says; where it says
427
- nothing, name the address after the invitation, and the dock routes it
428
- there. Where that address is on the web, `pilot` opens the web carrier
429
- first. With `--via far`, any command is asked of the far harbor as its
430
- owner, sealed over its carrier, except `own` and `disown`, which stay
431
- the far root's. Every ward holds far beings this way, a ward or any
432
- other being whose invitation
433
- carries the notes `{ owner: true }`, each under a name, asked with
434
- `pilot { name, method, args }` and let go with `drop { name }`.
122
+ // The house's code is a module on this origin, and its rows live in IndexedDB.
123
+ await ground.hand({
124
+ faculty: 'houses',
125
+ method: 'add',
126
+ args: { name: 'main', memory: { body: 'indexeddb' }, classes: { body: 'origin', at: '/house/index.js' } },
127
+ });
435
128
 
436
- `harbor.ask(request)` is the same request in code, for any other front:
437
- `{ ward?, method?, args? }` in, one JSON answer out.
438
-
439
- ## Moving a harbor
440
-
441
- A harbor moves to another machine by its bytes, with no harbor open:
442
-
443
- ```sh
444
- nervur export --with-seed --dir ./harbor > harbor.json
445
- nervur import harbor.json --dir ./elsewhere
129
+ console.log(await ground.hand({ house: 'main', method: 'hello', args: { name: 'Ada' } }));
446
130
  ```
447
131
 
448
- `export` reads the folder's sealed places, and carries the seed only
449
- where you ask for it. `import` writes them into a folder that holds none.
450
- A package with no seed lands where custody already holds the one it was
451
- sealed under. In code, `copyPackage(from, to)` carries every place of one
452
- memory into another.
132
+ Every tab of the origin reaches the one ground, and when the tab running
133
+ it closes, the next opens it from the same storage. Its seeds are sealed
134
+ under a key the browser never hands out. Any script on the origin can
135
+ use them, so give the ground an origin of its own, with a strict content
136
+ security policy. The page and the house's module must share one copy of
137
+ `nervur/being`, as a bundler's shared chunk gives.
138
+
139
+ An app on a phone opens the same ground with `AppGround` from
140
+ `nervur/app`, on the Keychain or the Keystore and a store the system
141
+ keeps. `AUTHORING.md` shows both.
142
+
143
+ ## Entries
144
+
145
+ | Entry | For |
146
+ | --- | --- |
147
+ | `nervur/being` | writing a being: `Being`, `s`, `need`, `Args`, `Result` |
148
+ | `nervur` | any engine: `Ground`, `House` and the bodies they take |
149
+ | `nervur/node` | a ground on Node: `NodeGround`, the `nervur` command, and its bodies |
150
+ | `nervur/browser` | a ground in a page or its service worker: `BrowserGround` and its bodies |
151
+ | `nervur/app` | a ground in a phone's app: `AppGround`, and the two interfaces its shell fills |
152
+ | `nervur/serve` | a faculty's program in JavaScript: `serve` |
153
+ | `nervur/bench` | tests: `Bench`, `BenchGround`, `FakeNetwork` and the fakes of every body |
453
154
 
454
155
  ## License
455
156
 
456
- Apache-2.0. Copyright 2026 Bookarest Digital SRL. See LICENSE and NOTICE.
457
-
458
- [Quo](https://quo.systems) is a separate work, Razvan Gherghina's, also
459
- under Apache-2.0, and its spec names no kit. `nervur` is Quo's first
460
- implementation and says so gladly: the protocol owes this package
461
- nothing, and where the two disagree the spec wins.
157
+ Apache-2.0, © Bookarest Digital SRL. Quo is a separate work, under its
158
+ own license. See `NOTICE`.
@@ -0,0 +1,18 @@
1
+ import { BrowserGround, type BrowserGroundOptions } from '../browser/browser-ground.ts';
2
+ import { type NativeSecrets, type NativeStore } from './native.ts';
3
+ /** What the shell hands the ground: its secret store and its native store. */
4
+ export interface NativeShell {
5
+ readonly secrets: NativeSecrets;
6
+ readonly store: NativeStore;
7
+ }
8
+ export interface AppGroundOptions extends Omit<BrowserGroundOptions, 'platform'> {
9
+ readonly shell: NativeShell;
10
+ /** Loads a module of classes by URL, where the app's build hands its own. */
11
+ readonly load?: (href: string) => Promise<unknown>;
12
+ /** Where its classes stand; the web view's own origin where omitted. */
13
+ readonly origin?: string;
14
+ }
15
+ export declare const AppGround: Readonly<{
16
+ /** The app's ground: a BrowserGround whose custody and memory are the shell's own. */
17
+ open({ shell, load, origin, ...options }: AppGroundOptions): Promise<BrowserGround>;
18
+ }>;
@@ -0,0 +1,25 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // The ground in a phone's app: a BrowserGround in the shell's web view,
3
+ // on the two bodies the shell hands in. Its seeds rest in the platform's
4
+ // Keychain or Keystore, and its memory in a native store the system never
5
+ // evicts. The code arrives signed in the app's bundle, and one web view
6
+ // runs, so the lock is taken at once. A wake by push is the app's own
7
+ // recipe's faculty, since the library ships no faculty.
8
+ import { BrowserGround } from '../browser/browser-ground.js';
9
+ import { NativeCustody, NativeMemory } from './native.js';
10
+ export const AppGround = Object.freeze({
11
+ /** The app's ground: a BrowserGround whose custody and memory are the shell's own. */
12
+ open({ shell, load, origin, ...options }) {
13
+ return BrowserGround.open({
14
+ ...options,
15
+ platform: {
16
+ custody: async () => new NativeCustody(shell.secrets),
17
+ memory: async (name) => new NativeMemory(shell.store, name),
18
+ // The system keeps an app's own store, so there is nothing to ask.
19
+ persist: async () => true,
20
+ ...(load === undefined ? {} : { load }),
21
+ ...(origin === undefined ? {} : { origin }),
22
+ },
23
+ });
24
+ },
25
+ });
@@ -0,0 +1,2 @@
1
+ export { AppGround, type AppGroundOptions, type NativeShell } from './app-ground.ts';
2
+ export { NativeCustody, NativeMemory, type NativeSecrets, type NativeStore } from './native.ts';
@@ -0,0 +1,5 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // `nervur/app`: the ground of a phone's app, a BrowserGround on the bodies
3
+ // its shell hands in, and the contracts a shell's native code fills.
4
+ export { AppGround } from './app-ground.js';
5
+ export { NativeCustody, NativeMemory } from './native.js';