nervur 0.21.4 → 0.22.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.
Files changed (339) hide show
  1. package/README.md +215 -158
  2. package/dist/browser.js +4 -3
  3. package/dist/cli.js +16 -0
  4. package/dist/{being → core/being}/being.js +10 -0
  5. package/dist/{being → core/being}/faculty.js +5 -2
  6. package/dist/{being → core/being}/index.d.ts +1 -1
  7. package/dist/{being → core/being}/index.js +1 -1
  8. package/dist/{being → core/being}/kind.d.ts +2 -0
  9. package/dist/{being → core/being}/kind.js +6 -0
  10. package/dist/{being → core/being}/types.js +1 -1
  11. package/dist/{browser → core/browser}/index.d.ts +6 -5
  12. package/dist/{browser → core/browser}/index.js +10 -10
  13. package/dist/{browser → core/browser}/worker.d.ts +2 -3
  14. package/dist/{browser → core/browser}/worker.js +8 -11
  15. package/dist/{cli → core/cli}/command.d.ts +4 -4
  16. package/dist/{cli → core/cli}/command.js +116 -66
  17. package/dist/{cli → core/cli}/edge.js +4 -2
  18. package/dist/core/cli/harbor.d.ts +25 -0
  19. package/dist/{cli → core/cli}/harbor.js +45 -33
  20. package/dist/{contract → core/contract}/index.d.ts +6 -5
  21. package/dist/{contract → core/contract}/index.js +8 -9
  22. package/dist/core/contract/link.d.ts +4 -0
  23. package/dist/core/contract/link.js +45 -0
  24. package/dist/{crypto → core/crypto}/ed25519.js +22 -14
  25. package/dist/core/crypto/subtle.d.ts +3 -0
  26. package/dist/core/crypto/subtle.js +11 -0
  27. package/dist/core/crypto/x25519.js +24 -0
  28. package/dist/core/edge/index.d.ts +164 -0
  29. package/dist/core/edge/index.js +739 -0
  30. package/dist/core/edge/kit.d.ts +2 -0
  31. package/dist/core/edge/kit.js +2 -0
  32. package/dist/core/git/http.d.ts +6 -0
  33. package/dist/core/git/http.js +102 -0
  34. package/dist/core/git/index.d.ts +5 -0
  35. package/dist/core/git/index.js +10 -0
  36. package/dist/core/git/object.d.ts +40 -0
  37. package/dist/core/git/object.js +103 -0
  38. package/dist/core/git/pack.d.ts +9 -0
  39. package/dist/core/git/pack.js +171 -0
  40. package/dist/core/git/store.d.ts +23 -0
  41. package/dist/core/git/store.js +120 -0
  42. package/dist/core/git/zlib.d.ts +6 -0
  43. package/dist/core/git/zlib.js +210 -0
  44. package/dist/core/harbor/carrying.d.ts +51 -0
  45. package/dist/core/harbor/carrying.js +69 -0
  46. package/dist/core/harbor/catalogue.d.ts +33 -0
  47. package/dist/core/harbor/catalogue.js +365 -0
  48. package/dist/core/harbor/dna.d.ts +13 -0
  49. package/dist/core/harbor/dna.js +120 -0
  50. package/dist/{harbor → core/harbor}/dock.d.ts +22 -13
  51. package/dist/core/harbor/dock.js +381 -0
  52. package/dist/core/harbor/harbor.d.ts +16 -0
  53. package/dist/core/harbor/harbor.js +438 -0
  54. package/dist/core/harbor/index.d.ts +11 -0
  55. package/dist/{harbor → core/harbor}/index.js +5 -5
  56. package/dist/core/harbor/memory.d.ts +10 -0
  57. package/dist/core/harbor/memory.js +25 -0
  58. package/dist/{harbor → core/harbor}/package.d.ts +0 -1
  59. package/dist/{harbor → core/harbor}/package.js +9 -9
  60. package/dist/core/harbor/probe.d.ts +22 -0
  61. package/dist/core/harbor/probe.js +15 -0
  62. package/dist/core/harbor/registry.d.ts +15 -0
  63. package/dist/{harbor → core/harbor}/registry.js +26 -10
  64. package/dist/core/harbor/root-line.d.ts +7 -0
  65. package/dist/core/harbor/root-line.js +9 -0
  66. package/dist/{harbor → core/harbor}/terrain.d.ts +9 -6
  67. package/dist/{harbor → core/harbor}/terrain.js +5 -4
  68. package/dist/core/http/index.d.ts +2 -0
  69. package/dist/{http → core/http}/index.js +3 -5
  70. package/dist/{line → core/line}/answer.d.ts +2 -2
  71. package/dist/{line → core/line}/frame.d.ts +0 -5
  72. package/dist/{line → core/line}/frame.js +0 -4
  73. package/dist/core/line/ground.js +7 -0
  74. package/dist/core/line/index.d.ts +4 -0
  75. package/dist/core/line/index.js +8 -0
  76. package/dist/core/line/web.d.ts +12 -0
  77. package/dist/{line → core/line}/web.js +13 -77
  78. package/dist/{node → core/node}/index.d.ts +2 -15
  79. package/dist/core/node/index.js +124 -0
  80. package/dist/{pointer → core/pointer}/bodies.d.ts +7 -5
  81. package/dist/core/pointer/bodies.js +118 -0
  82. package/dist/core/pointer/index.d.ts +2 -0
  83. package/dist/{pointer → core/pointer}/index.js +1 -1
  84. package/dist/{pointer → core/pointer}/world.d.ts +13 -9
  85. package/dist/{pointer → core/pointer}/world.js +31 -16
  86. package/dist/{proof → core/proof}/contracts.d.ts +6 -2
  87. package/dist/{proof → core/proof}/contracts.js +11 -10
  88. package/dist/core/proof/index.d.ts +3 -0
  89. package/dist/{proof → core/proof}/index.js +2 -2
  90. package/dist/core/proof/law.d.ts +25 -0
  91. package/dist/core/proof/law.js +715 -0
  92. package/dist/{tcp → core/tcp}/index.d.ts +7 -4
  93. package/dist/{tcp → core/tcp}/index.js +11 -62
  94. package/dist/{ward/ward.d.ts → core/ward/house.d.ts} +24 -10
  95. package/dist/core/ward/house.js +473 -0
  96. package/dist/core/ward/index.d.ts +5 -0
  97. package/dist/core/ward/index.js +7 -0
  98. package/dist/{ward → core/ward}/partition.d.ts +1 -0
  99. package/dist/{ward → core/ward}/stance.d.ts +2 -2
  100. package/dist/{ward → core/ward}/stance.js +5 -2
  101. package/dist/{ward/ward-being.d.ts → core/ward/ward.d.ts} +14 -6
  102. package/dist/core/ward/ward.js +140 -0
  103. package/dist/core.d.ts +10 -0
  104. package/dist/core.js +19 -0
  105. package/dist/defaults/dock/index.d.ts +4 -0
  106. package/dist/defaults/dock/index.js +11 -0
  107. package/dist/defaults/index.d.ts +5 -0
  108. package/dist/defaults/index.js +10 -0
  109. package/dist/defaults/memory/index.d.ts +12 -0
  110. package/dist/defaults/memory/index.js +39 -0
  111. package/dist/defaults/tcp/index.d.ts +16 -0
  112. package/dist/defaults/tcp/index.js +82 -0
  113. package/dist/defaults/ward/index.d.ts +4 -0
  114. package/dist/defaults/ward/index.js +11 -0
  115. package/dist/defaults/web/index.d.ts +15 -0
  116. package/dist/defaults/web/index.js +90 -0
  117. package/dist/edge.js +4 -3
  118. package/dist/index.d.ts +1 -8
  119. package/dist/index.js +13 -18
  120. package/dist/kit.d.ts +4 -0
  121. package/dist/kit.js +12 -0
  122. package/dist/node.js +4 -3
  123. package/package.json +23 -18
  124. package/src/browser.ts +4 -3
  125. package/src/cli.ts +15 -0
  126. package/src/{being → core/being}/being.ts +4 -0
  127. package/src/{being → core/being}/faculty.ts +5 -2
  128. package/src/{being → core/being}/index.ts +1 -1
  129. package/src/{being → core/being}/kind.ts +7 -0
  130. package/src/{being → core/being}/types.ts +1 -1
  131. package/src/{browser → core/browser}/index.ts +16 -13
  132. package/src/{browser → core/browser}/worker.ts +11 -14
  133. package/src/{cli → core/cli}/command.ts +113 -66
  134. package/src/{cli → core/cli}/edge.ts +4 -2
  135. package/src/{cli → core/cli}/harbor.ts +48 -31
  136. package/src/{contract → core/contract}/index.ts +14 -14
  137. package/src/core/contract/link.ts +58 -0
  138. package/src/{crypto → core/crypto}/ed25519.ts +22 -14
  139. package/src/core/crypto/subtle.ts +13 -0
  140. package/src/core/crypto/x25519.ts +23 -0
  141. package/src/core/edge/index.ts +865 -0
  142. package/src/core/git/http.ts +103 -0
  143. package/src/core/git/index.ts +10 -0
  144. package/src/core/git/object.ts +116 -0
  145. package/src/core/git/pack.ts +147 -0
  146. package/src/core/git/store.ts +122 -0
  147. package/src/core/git/zlib.ts +197 -0
  148. package/src/core/harbor/carrying.ts +124 -0
  149. package/src/core/harbor/catalogue.ts +386 -0
  150. package/src/core/harbor/dna.ts +116 -0
  151. package/src/core/harbor/dock.ts +420 -0
  152. package/src/core/harbor/harbor.ts +433 -0
  153. package/src/core/harbor/index.ts +14 -0
  154. package/src/core/harbor/memory.ts +31 -0
  155. package/src/{harbor → core/harbor}/package.ts +15 -15
  156. package/src/core/harbor/probe.ts +39 -0
  157. package/src/{harbor → core/harbor}/registry.ts +28 -11
  158. package/src/core/harbor/root-line.ts +19 -0
  159. package/src/{harbor → core/harbor}/terrain.ts +14 -7
  160. package/src/{http → core/http}/index.ts +5 -8
  161. package/src/{line → core/line}/answer.ts +3 -2
  162. package/src/{line → core/line}/frame.ts +0 -5
  163. package/src/core/line/ground.ts +18 -0
  164. package/src/core/line/index.ts +8 -0
  165. package/src/{line → core/line}/web.ts +1 -105
  166. package/src/core/node/index.ts +139 -0
  167. package/src/core/pointer/bodies.ts +122 -0
  168. package/src/core/pointer/index.ts +4 -0
  169. package/src/{pointer → core/pointer}/world.ts +45 -21
  170. package/src/{proof → core/proof}/contracts.ts +18 -13
  171. package/src/{proof → core/proof}/index.ts +3 -3
  172. package/src/core/proof/law.ts +742 -0
  173. package/src/{stand → core/stand}/stand.ts +2 -2
  174. package/src/{tcp → core/tcp}/index.ts +17 -74
  175. package/src/core/ward/house.ts +524 -0
  176. package/src/core/ward/index.ts +7 -0
  177. package/src/{ward → core/ward}/partition.ts +5 -1
  178. package/src/{ward → core/ward}/stance.ts +5 -2
  179. package/src/core/ward/ward.ts +166 -0
  180. package/src/core.ts +55 -0
  181. package/src/defaults/dock/index.ts +12 -0
  182. package/src/defaults/index.ts +10 -0
  183. package/src/defaults/memory/index.ts +50 -0
  184. package/src/defaults/tcp/index.ts +89 -0
  185. package/src/defaults/ward/index.ts +12 -0
  186. package/src/defaults/web/index.ts +97 -0
  187. package/src/edge.ts +4 -3
  188. package/src/index.ts +13 -50
  189. package/src/kit.ts +15 -0
  190. package/src/node.ts +4 -3
  191. package/dist/cli/harbor.d.ts +0 -16
  192. package/dist/cli/main.js +0 -14
  193. package/dist/crypto/subtle.d.ts +0 -10
  194. package/dist/crypto/subtle.js +0 -29
  195. package/dist/crypto/x25519.js +0 -21
  196. package/dist/edge/index.d.ts +0 -81
  197. package/dist/edge/index.js +0 -400
  198. package/dist/harbor/carrying.d.ts +0 -17
  199. package/dist/harbor/carrying.js +0 -38
  200. package/dist/harbor/catalogue.d.ts +0 -28
  201. package/dist/harbor/catalogue.js +0 -109
  202. package/dist/harbor/dock.js +0 -236
  203. package/dist/harbor/harbor.d.ts +0 -45
  204. package/dist/harbor/harbor.js +0 -347
  205. package/dist/harbor/index.d.ts +0 -11
  206. package/dist/harbor/probe.d.ts +0 -18
  207. package/dist/harbor/probe.js +0 -15
  208. package/dist/harbor/registry.d.ts +0 -10
  209. package/dist/harbor/relay.d.ts +0 -15
  210. package/dist/harbor/relay.js +0 -406
  211. package/dist/harbor/root-line.d.ts +0 -9
  212. package/dist/harbor/root-line.js +0 -38
  213. package/dist/harbor/store.d.ts +0 -13
  214. package/dist/harbor/store.js +0 -53
  215. package/dist/http/index.d.ts +0 -4
  216. package/dist/line/ground.js +0 -9
  217. package/dist/line/index.d.ts +0 -5
  218. package/dist/line/index.js +0 -9
  219. package/dist/line/push.d.ts +0 -7
  220. package/dist/line/push.js +0 -92
  221. package/dist/line/web.d.ts +0 -30
  222. package/dist/node/index.js +0 -236
  223. package/dist/pointer/bodies.js +0 -80
  224. package/dist/pointer/index.d.ts +0 -2
  225. package/dist/proof/index.d.ts +0 -3
  226. package/dist/proof/law.d.ts +0 -90
  227. package/dist/proof/law.js +0 -591
  228. package/dist/tcp/frame.d.ts +0 -25
  229. package/dist/tcp/frame.js +0 -64
  230. package/dist/ward/index.d.ts +0 -6
  231. package/dist/ward/index.js +0 -8
  232. package/dist/ward/pilot.d.ts +0 -8
  233. package/dist/ward/pilot.js +0 -50
  234. package/dist/ward/ward-being.js +0 -82
  235. package/dist/ward/ward.js +0 -290
  236. package/src/cli/main.ts +0 -13
  237. package/src/crypto/subtle.ts +0 -33
  238. package/src/crypto/x25519.ts +0 -21
  239. package/src/edge/index.ts +0 -490
  240. package/src/harbor/carrying.ts +0 -56
  241. package/src/harbor/catalogue.ts +0 -134
  242. package/src/harbor/dock.ts +0 -265
  243. package/src/harbor/harbor.ts +0 -381
  244. package/src/harbor/index.ts +0 -14
  245. package/src/harbor/probe.ts +0 -34
  246. package/src/harbor/relay.ts +0 -418
  247. package/src/harbor/root-line.ts +0 -39
  248. package/src/harbor/store.ts +0 -69
  249. package/src/line/ground.ts +0 -19
  250. package/src/line/index.ts +0 -9
  251. package/src/line/push.ts +0 -112
  252. package/src/node/index.ts +0 -241
  253. package/src/pointer/bodies.ts +0 -82
  254. package/src/pointer/index.ts +0 -4
  255. package/src/proof/law.ts +0 -591
  256. package/src/ward/index.ts +0 -8
  257. package/src/ward/pilot.ts +0 -50
  258. package/src/ward/ward-being.ts +0 -103
  259. package/src/ward/ward.ts +0 -328
  260. /package/dist/{cli/main.d.ts → cli.d.ts} +0 -0
  261. /package/dist/{being → core/being}/being.d.ts +0 -0
  262. /package/dist/{being → core/being}/digest.d.ts +0 -0
  263. /package/dist/{being → core/being}/digest.js +0 -0
  264. /package/dist/{being → core/being}/faculty.d.ts +0 -0
  265. /package/dist/{being → core/being}/types.d.ts +0 -0
  266. /package/dist/{being → core/being}/words.d.ts +0 -0
  267. /package/dist/{being → core/being}/words.js +0 -0
  268. /package/dist/{cli → core/cli}/edge.d.ts +0 -0
  269. /package/dist/{crypto → core/crypto}/aes.d.ts +0 -0
  270. /package/dist/{crypto → core/crypto}/aes.js +0 -0
  271. /package/dist/{crypto → core/crypto}/bytes.d.ts +0 -0
  272. /package/dist/{crypto → core/crypto}/bytes.js +0 -0
  273. /package/dist/{crypto → core/crypto}/ed25519.d.ts +0 -0
  274. /package/dist/{crypto → core/crypto}/hash.d.ts +0 -0
  275. /package/dist/{crypto → core/crypto}/hash.js +0 -0
  276. /package/dist/{crypto → core/crypto}/index.d.ts +0 -0
  277. /package/dist/{crypto → core/crypto}/index.js +0 -0
  278. /package/dist/{crypto → core/crypto}/json.d.ts +0 -0
  279. /package/dist/{crypto → core/crypto}/json.js +0 -0
  280. /package/dist/{crypto → core/crypto}/mlkem.d.ts +0 -0
  281. /package/dist/{crypto → core/crypto}/mlkem.js +0 -0
  282. /package/dist/{crypto → core/crypto}/x25519.d.ts +0 -0
  283. /package/dist/{folder → core/folder}/index.d.ts +0 -0
  284. /package/dist/{folder → core/folder}/index.js +0 -0
  285. /package/dist/{http → core/http}/websocket.d.ts +0 -0
  286. /package/dist/{http → core/http}/websocket.js +0 -0
  287. /package/dist/{line → core/line}/answer.js +0 -0
  288. /package/dist/{line → core/line}/ground.d.ts +0 -0
  289. /package/dist/{proof → core/proof}/expect.d.ts +0 -0
  290. /package/dist/{proof → core/proof}/expect.js +0 -0
  291. /package/dist/{quo → core/quo}/address.d.ts +0 -0
  292. /package/dist/{quo → core/quo}/address.js +0 -0
  293. /package/dist/{quo → core/quo}/door.d.ts +0 -0
  294. /package/dist/{quo → core/quo}/door.js +0 -0
  295. /package/dist/{quo → core/quo}/index.d.ts +0 -0
  296. /package/dist/{quo → core/quo}/index.js +0 -0
  297. /package/dist/{quo → core/quo}/invitation.d.ts +0 -0
  298. /package/dist/{quo → core/quo}/invitation.js +0 -0
  299. /package/dist/{quo → core/quo}/keys.d.ts +0 -0
  300. /package/dist/{quo → core/quo}/keys.js +0 -0
  301. /package/dist/{quo → core/quo}/payload.d.ts +0 -0
  302. /package/dist/{quo → core/quo}/payload.js +0 -0
  303. /package/dist/{quo → core/quo}/relations.d.ts +0 -0
  304. /package/dist/{quo → core/quo}/relations.js +0 -0
  305. /package/dist/{quo → core/quo}/reply.d.ts +0 -0
  306. /package/dist/{quo → core/quo}/reply.js +0 -0
  307. /package/dist/{quo → core/quo}/seal.d.ts +0 -0
  308. /package/dist/{quo → core/quo}/seal.js +0 -0
  309. /package/dist/{quo → core/quo}/standing.d.ts +0 -0
  310. /package/dist/{quo → core/quo}/standing.js +0 -0
  311. /package/dist/{ward → core/ward}/allowance.d.ts +0 -0
  312. /package/dist/{ward → core/ward}/allowance.js +0 -0
  313. /package/dist/{ward → core/ward}/cells.d.ts +0 -0
  314. /package/dist/{ward → core/ward}/cells.js +0 -0
  315. /package/dist/{ward → core/ward}/partition.js +0 -0
  316. /package/src/{being → core/being}/digest.ts +0 -0
  317. /package/src/{being → core/being}/words.ts +0 -0
  318. /package/src/{crypto → core/crypto}/aes.ts +0 -0
  319. /package/src/{crypto → core/crypto}/bytes.ts +0 -0
  320. /package/src/{crypto → core/crypto}/hash.ts +0 -0
  321. /package/src/{crypto → core/crypto}/index.ts +0 -0
  322. /package/src/{crypto → core/crypto}/json.ts +0 -0
  323. /package/src/{crypto → core/crypto}/mlkem.ts +0 -0
  324. /package/src/{folder → core/folder}/index.ts +0 -0
  325. /package/src/{http → core/http}/websocket.ts +0 -0
  326. /package/src/{proof → core/proof}/expect.ts +0 -0
  327. /package/src/{quo → core/quo}/address.ts +0 -0
  328. /package/src/{quo → core/quo}/door.ts +0 -0
  329. /package/src/{quo → core/quo}/index.ts +0 -0
  330. /package/src/{quo → core/quo}/invitation.ts +0 -0
  331. /package/src/{quo → core/quo}/keys.ts +0 -0
  332. /package/src/{quo → core/quo}/payload.ts +0 -0
  333. /package/src/{quo → core/quo}/relations.ts +0 -0
  334. /package/src/{quo → core/quo}/reply.ts +0 -0
  335. /package/src/{quo → core/quo}/seal.ts +0 -0
  336. /package/src/{quo → core/quo}/standing.ts +0 -0
  337. /package/src/{stand → core/stand}/main.ts +0 -0
  338. /package/src/{ward → core/ward}/allowance.ts +0 -0
  339. /package/src/{ward → core/ward}/cells.ts +0 -0
package/dist/tcp/frame.js DELETED
@@ -1,64 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // The frames of Quo over TCP, `quo/CARRIER-TCP.md`:
3
- //
4
- // frame = length (4, big-endian) || kind (1) || id (4, big-endian) || rest
5
- // 00 ask rest = ward pk (64) || box
6
- // 01 reply rest = box
7
- // 02 nothing rest = empty
8
- //
9
- // A reader says a stream is not a frame as soon as its bytes say so, and
10
- // reads nothing after it.
11
- import { concat } from '../crypto/index.js';
12
- export const ASK = 0;
13
- export const REPLY = 1;
14
- export const NOTHING = 2;
15
- export const MAX_BODY = 1_048_645;
16
- const PK = 64;
17
- const frame = (kind, id, ...rest) => {
18
- const head = new Uint8Array(9);
19
- const view = new DataView(head.buffer);
20
- view.setUint32(0, 5 + rest.reduce((n, r) => n + r.length, 0));
21
- head[4] = kind;
22
- view.setUint32(5, id >>> 0);
23
- return concat(head, ...rest);
24
- };
25
- export const askFrame = (id, pk, box) => frame(ASK, id, pk, box);
26
- export const replyFrame = (id, box) => frame(REPLY, id, box);
27
- export const nothingFrame = (id) => frame(NOTHING, id);
28
- // Whether a body of this length, and this first byte when known, is no frame.
29
- const notAFrame = (length, kind) => length > MAX_BODY || length < 5 || (kind !== undefined && (kind > NOTHING || (kind === ASK && length < 5 + PK) || (kind === NOTHING && length !== 5)));
30
- export class FrameReader {
31
- #buffer = new Uint8Array(0);
32
- #bad = false;
33
- // True once bytes that are not a frame arrived; nothing is read after.
34
- get bad() {
35
- return this.#bad;
36
- }
37
- push(chunk) {
38
- if (this.#bad)
39
- return [];
40
- this.#buffer = this.#buffer.length === 0 ? chunk.slice() : concat(this.#buffer, chunk);
41
- const out = [];
42
- while (this.#buffer.length >= 4) {
43
- const view = new DataView(this.#buffer.buffer, this.#buffer.byteOffset);
44
- const length = view.getUint32(0);
45
- if (notAFrame(length, this.#buffer.length > 4 ? this.#buffer[4] : undefined)) {
46
- this.#bad = true;
47
- this.#buffer = new Uint8Array(0);
48
- return out;
49
- }
50
- if (this.#buffer.length < 4 + length)
51
- break;
52
- const body = this.#buffer.subarray(4, 4 + length);
53
- this.#buffer = this.#buffer.slice(4 + length);
54
- const id = new DataView(body.buffer, body.byteOffset).getUint32(1);
55
- if (body[0] === ASK)
56
- out.push({ kind: 'ask', id, pk: body.slice(5, 5 + PK), box: body.slice(5 + PK) });
57
- else if (body[0] === REPLY)
58
- out.push({ kind: 'reply', id, box: body.slice(5) });
59
- else
60
- out.push({ kind: 'nothing', id });
61
- }
62
- return out;
63
- }
64
- }
@@ -1,6 +0,0 @@
1
- export { allow, CEILING, DEFAULT } from './allowance.ts';
2
- export { HEAD_ROW, Partition, type BeingRow, type Head, type StandingRow } from './partition.ts';
3
- export { DEPTH } from './stance.ts';
4
- export { DOCK, Ward, type Catalogue, type Lender, type Routes, type WardParts } from './ward.ts';
5
- export { ownerAsk, PILOT, pilots, rootAsk, WardBeing, type Steward, type WardBeingStance } from './ward-being.ts';
6
- export { Pilot } from './pilot.ts';
@@ -1,8 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // The ward: its partition, its stances, its ward-being, and the ward.
3
- export { allow, CEILING, DEFAULT } from './allowance.js';
4
- export { HEAD_ROW, Partition } from './partition.js';
5
- export { DEPTH } from './stance.js';
6
- export { DOCK, Ward } from './ward.js';
7
- export { ownerAsk, PILOT, pilots, rootAsk, WardBeing } from './ward-being.js';
8
- export { Pilot } from './pilot.js';
@@ -1,8 +0,0 @@
1
- import { Being, type AskSpec, type JsonObject } from '../being/index.ts';
2
- export declare class Pilot extends Being {
3
- static readonly kind: string;
4
- static asks: Record<string, AskSpec>;
5
- hold(args: JsonObject): Promise<JsonObject>;
6
- pilot(args: JsonObject): Promise<JsonObject>;
7
- drop(): JsonObject;
8
- }
@@ -1,50 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // The pilot: a kit being that holds an owner's relation on another ward's
3
- // ward-being, so whoever pilots her ward pilots that ward from afar. The
4
- // relation is an ordinary standing, kept in her ward's partition, so it
5
- // moves its keys and survives a restart like any other.
6
- //
7
- // hold { invitation } the owner invitation taken, under `far`
8
- // pilot { method?, args? } the far ward-being asked, as its owner
9
- // drop the relation let go
10
- //
11
- // She is the kit's, of kind `org.nervur.pilot`, and answers whoever pilots
12
- // her own ward alone.
13
- import { Being, isSilence, isWord, told } from '../being/index.js';
14
- import { readInvitation } from '../quo/index.js';
15
- import { ownerAsk, PILOT } from './ward-being.js';
16
- // The standing id the far ward-being is held under.
17
- const FAR = 'far';
18
- const object = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
19
- export class Pilot extends Being {
20
- static kind = PILOT;
21
- static asks = {
22
- hold: ownerAsk('an owner invitation on a far ward, held from now on', { required: ['invitation'] }),
23
- pilot: ownerAsk('the far ward-being, asked as its owner'),
24
- drop: ownerAsk('the far ward let go'),
25
- };
26
- async hold(args) {
27
- const invitation = readInvitation(args.invitation);
28
- if (invitation === null)
29
- return { error: 'no invitation' };
30
- if (this.stance.standings.get(FAR))
31
- return { error: 'a ward is held' };
32
- return (await this.stance.standings.take(FAR, invitation)) === null ? { error: 'not taken' } : { held: invitation.ward };
33
- }
34
- async pilot(args) {
35
- if ((args.method !== undefined && typeof args.method !== 'string') || (args.args !== undefined && !object(args.args)))
36
- return { error: 'method is text, args an object' };
37
- const standing = this.stance.standings.get(FAR);
38
- if (!standing)
39
- return { error: 'no ward is held' };
40
- const out = await standing.ask(args.method, args.args ?? {});
41
- if (isSilence(out))
42
- return { error: 'silence' };
43
- if (isWord(out))
44
- return { error: told(out) };
45
- return { answer: out };
46
- }
47
- drop() {
48
- return this.stance.standings.remove(FAR) ? { dropped: true } : { error: 'no ward is held' };
49
- }
50
- }
@@ -1,82 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // The ward-being: the first being of every ward, the ward itself. Her asks
3
- // are the root's, shown and answered to `OWNER` alone.
4
- import { Being, isSilence, isWord, KIT, OWNER, told } from '../being/index.js';
5
- // Whoever pilots a ward: the root, holding its unsealed ask, or an owner,
6
- // an occupant of the ward-being the root invited as one.
7
- export const pilots = (asker, notes) => asker.id === OWNER || notes?.owner === true;
8
- // An ask whoever pilots the ward may make.
9
- export const ownerAsk = (description, input = {}) => ({ description, input: { type: 'object', ...input }, for: pilots });
10
- // An ask the root alone may make, so a carried key pilots but never hands
11
- // piloting on.
12
- export const rootAsk = (description, input = {}) => ({ description, input: { type: 'object', ...input }, for: (asker) => asker.id === OWNER });
13
- // The one kit kind the root boots: every other kit class stands where the
14
- // kit puts it.
15
- export const PILOT = 'org.nervur.pilot';
16
- const text = (v) => typeof v === 'string';
17
- const object = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
18
- export class WardBeing extends Being {
19
- static kind = 'org.nervur.ward-being';
20
- static asks = {
21
- boot: ownerAsk('a new being of this ward', { required: ['key', 'class'] }),
22
- unboot: ownerAsk('a being out, with every relation she holds', { required: ['being'] }),
23
- public: ownerAsk('the being a stranger reaches, or none', { required: ['key'] }),
24
- invite: ownerAsk('an invitation on a being of this ward', { required: ['being', 'id'] }),
25
- ask: ownerAsk('a being of this ward, asked as the owner; with no being, the public being asked as nobody'),
26
- own: rootAsk('an invitation for an owner of this ward, under an id', { required: ['id'] }),
27
- disown: rootAsk('an owner no more', { required: ['id'] }),
28
- };
29
- steward;
30
- constructor(stance) {
31
- super(stance);
32
- this.steward = stance.steward;
33
- }
34
- describe(asker) {
35
- const { asks } = super.describe(asker);
36
- return { asks, notes: pilots(asker, this.notes(asker)) ? { pk: this.steward.pk(), beings: this.steward.beings() } : {} };
37
- }
38
- async own(args) {
39
- if (!text(args.id))
40
- return { error: 'id is text' };
41
- return (await this.stance.occupants.invite(args.id, { owner: true })) ?? { error: 'id taken' };
42
- }
43
- disown(args) {
44
- if (!text(args.id) || this.stance.occupants.notes(args.id)?.owner !== true)
45
- return { error: 'no such owner' };
46
- this.stance.occupants.remove(args.id);
47
- return { disowned: args.id };
48
- }
49
- async boot(args) {
50
- if (!text(args.key) || !text(args.class))
51
- return { error: 'key and class are text' };
52
- if (args.class.startsWith(KIT) && args.class !== PILOT)
53
- return { error: 'no such class' };
54
- const out = await this.steward.boot(args.key, args.class);
55
- return out === 'booted' ? { booted: args.key } : { error: out };
56
- }
57
- unboot(args) {
58
- return text(args.being) && this.steward.unboot(args.being) ? { unbooted: args.being } : { error: 'no such being' };
59
- }
60
- public(args) {
61
- if (args.key !== null && !text(args.key))
62
- return { error: 'key is text or null' };
63
- return this.steward.publish(args.key) ? { public: args.key } : { error: 'no such being' };
64
- }
65
- async invite(args) {
66
- if (!text(args.being) || !text(args.id) || (args.notes !== undefined && !object(args.notes)))
67
- return { error: 'being and id are text, notes an object' };
68
- const invitation = await this.steward.invite(args.being, args.id, args.notes ?? {});
69
- return invitation ?? { error: 'not invited' };
70
- }
71
- async ask(args) {
72
- if ((args.being !== undefined && !text(args.being)) || (args.method !== undefined && !text(args.method)) || (args.args !== undefined && !object(args.args))) {
73
- return { error: 'being and method are text, args an object' };
74
- }
75
- const out = await this.steward.ask(args.being ?? null, args.method, args.args ?? {});
76
- if (isSilence(out))
77
- return { error: 'silence' };
78
- if (isWord(out))
79
- return { error: told(out) };
80
- return { answer: out };
81
- }
82
- }
package/dist/ward/ward.js DELETED
@@ -1,290 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // The ward: one door, one partition, and the beings behind the door. It
3
- // unpacks from its seed, its memory and a catalogue of classes, the
4
- // ward-being first and every other being from her own row, and it stands
5
- // what is behind its door for `quo/`.
6
- import { readValue, writeValue } from '../crypto/index.js';
7
- import { Door, readInvitation, WardKey } from '../quo/index.js';
8
- import { digest, isSilence, isWord, kindOf, OWNER, silence, WARD, word } from '../being/index.js';
9
- import { Partition, PartitionRelations } from './partition.js';
10
- import { DEPTH, WardStance } from './stance.js';
11
- import { WardBeing } from './ward-being.js';
12
- // The standing every hosted ward's ward-being holds on the dock.
13
- export const DOCK = 'dock';
14
- const lends = (being) => typeof being.offer === 'function';
15
- class RootStance extends WardStance {
16
- steward;
17
- constructor(inside, row, steward) {
18
- super(inside, WARD, row);
19
- this.steward = steward;
20
- }
21
- }
22
- export class Ward {
23
- key;
24
- partition;
25
- door;
26
- clock;
27
- #parts;
28
- #residents = new Map();
29
- #birthing = new Set();
30
- constructor(parts, key) {
31
- this.#parts = parts;
32
- this.key = key;
33
- this.clock = parts.clock;
34
- this.partition = new Partition(parts.memory);
35
- this.door = new Door(key, new PartitionRelations(this.partition), this, parts.entropy.drawer);
36
- }
37
- // The ward-being first, then every being her row names. A class the
38
- // catalogue lacks, or one that throws, leaves that being absent and her
39
- // row as it was.
40
- static async unpack(parts) {
41
- const ward = new Ward(parts, await WardKey.from(parts.seed));
42
- if (!ward.partition.being(WARD)) {
43
- ward.partition.beings[WARD] = { class: '', cells: {}, occupants: {}, standings: {} };
44
- ward.partition.told(WARD);
45
- ward.partition.toldHead();
46
- }
47
- const own = ward.partition.being(WARD);
48
- const stance = new RootStance(ward, own, ward.#steward);
49
- const being = parts.root ? parts.root(stance) : new WardBeing(stance);
50
- own.class = kindOf(being.constructor);
51
- ward.#residents.set(WARD, { being, row: own, stance });
52
- // The standing on the dock is kept at once: its heir is spent, so a
53
- // restart before the ward's first keep would find no way back.
54
- if (parts.dock && !Object.hasOwn(own.standings, DOCK) && (await stance.standings.take(DOCK, parts.dock)) !== null && !(await ward.partition.kept())) {
55
- throw new Error('the standing on the dock was not kept');
56
- }
57
- for (const [key, row] of Object.entries(ward.partition.beings)) {
58
- const C = key === WARD ? undefined : parts.catalogue.classOf(row.class);
59
- if (C)
60
- ward.#bear(key, row, C);
61
- }
62
- return ward;
63
- }
64
- get pk() {
65
- return this.key.pk;
66
- }
67
- get draw() {
68
- return this.#parts.entropy.drawer;
69
- }
70
- get wardBeing() {
71
- return this.#residents.get(WARD).being;
72
- }
73
- // The being standing under a key, for the harbor's own faculties.
74
- being(key) {
75
- return this.#residents.get(key)?.being;
76
- }
77
- // Every being her row names, of the class the catalogue now resolves for
78
- // her kind: an absent being is born, and one whose class a module
79
- // replaced is born again of the new class on the stance she holds, so
80
- // her relations and their lanes stay hers. A new class that throws at
81
- // birth leaves her as she was.
82
- bearAnew() {
83
- for (const [key, row] of Object.entries(this.partition.beings)) {
84
- const C = key === WARD ? undefined : this.#parts.catalogue.classOf(row.class);
85
- const resident = this.#residents.get(key);
86
- if (!C || resident?.being.constructor === C)
87
- continue;
88
- if (!resident) {
89
- this.#bear(key, row, C);
90
- continue;
91
- }
92
- try {
93
- resident.being = new C(resident.stance);
94
- }
95
- catch {
96
- continue;
97
- }
98
- }
99
- }
100
- // The unsealed ask: the ward-being, asked by whoever holds this ward.
101
- // It reaches every being of the ward through the ward-being, so every
102
- // row is put back where the memory refuses.
103
- async root(method, args = {}) {
104
- return this.#kept(Object.keys(this.partition.beings), () => this.#answer(WARD, { id: OWNER }, method, args));
105
- }
106
- // An answer, kept. Where the memory refuses, what the beings wrote is put
107
- // back and the answer is silence. What their relations stand on is not
108
- // put back: a relation's keys move only as far as its standing follows.
109
- async #kept(keys, work) {
110
- const before = keys.flatMap((key) => {
111
- const row = this.partition.being(key);
112
- return row ? [[key, row.cells, JSON.stringify(row.cells)]] : [];
113
- });
114
- const out = await work();
115
- if (await this.partition.kept())
116
- return out;
117
- for (const [key, cells, was] of before) {
118
- if (JSON.stringify(cells) === was)
119
- continue;
120
- for (const k of Object.keys(cells))
121
- delete cells[k];
122
- for (const [k, v] of Object.entries(JSON.parse(was)))
123
- Object.defineProperty(cells, k, { value: v, enumerable: true, writable: true, configurable: true });
124
- this.partition.told(key);
125
- }
126
- return silence;
127
- }
128
- // Behind: the zero head reaches the public being, an heir the being that
129
- // invited it.
130
- get zero() {
131
- const key = this.partition.head.public;
132
- return key !== null && this.#residents.has(key);
133
- }
134
- async answer(heir, p) {
135
- const bound = heir === null ? undefined : this.partition.head.bind[heir];
136
- const key = heir === null ? this.partition.head.public : bound?.being;
137
- const asker = bound ? { id: bound.id } : {};
138
- const args = p.args === undefined ? {} : readValue(p.args, DEPTH + 1);
139
- if (key === null || key === undefined || typeof args !== 'object' || args === null || Array.isArray(args))
140
- return { silence: true };
141
- const out = await this.#kept([key], () => this.#answer(key, asker, p.method, args));
142
- const object = isSilence(out) || isWord(out) ? undefined : writeValue(out, DEPTH);
143
- if (object === undefined)
144
- return { silence: true };
145
- const being = this.#residents.get(key)?.being;
146
- const seen = p.method === undefined || !being?.describe ? null : await digest(being.describe(asker));
147
- return { object, seen };
148
- }
149
- // Every path that reaches a being's answer. A throw, a word out of her,
150
- // or nothing at all is silence.
151
- async #answer(key, asker, method, args) {
152
- const resident = this.#residents.get(key);
153
- if (!resident)
154
- return silence;
155
- let out;
156
- try {
157
- out = await resident.being.answer(asker, method, args);
158
- }
159
- catch {
160
- return silence;
161
- }
162
- return out === undefined || isWord(out) ? silence : out;
163
- }
164
- // Inside: what every stance of this ward stands on.
165
- // One path through a door for every ask, this ward's own included.
166
- async send(pk, bytes) {
167
- if (pk === this.pk)
168
- return (await this.door.arrive(bytes)).bytes;
169
- return this.#parts.carrier.carry(pk, bytes);
170
- }
171
- // A lend: the ward-being lends herself, as the dock does, or asks the dock
172
- // through her standing.
173
- async offer(contract) {
174
- const own = this.#residents.get(WARD);
175
- if (lends(own.being))
176
- return own.being.offer(contract);
177
- const out = await own.stance.standings.get(DOCK)?.ask('lend', { contract });
178
- return readInvitation(out?.invitation);
179
- }
180
- async retract(contract, heir) {
181
- const own = this.#residents.get(WARD);
182
- if (lends(own.being))
183
- return own.being.withdraw(contract, heir);
184
- await own.stance.standings.get(DOCK)?.ask('retract', { contract, heir });
185
- }
186
- reach() {
187
- return this.#parts.routes?.reach() ?? [];
188
- }
189
- learn(ward, at) {
190
- return this.#parts.routes?.learn(ward, at) ?? Promise.resolve();
191
- }
192
- live(key, row) {
193
- return this.#residents.get(key)?.row === row;
194
- }
195
- // A being boots another of this ward. With an id, the new being invites
196
- // her maker under the maker's key, and the maker takes it under id; a
197
- // relation that could not be made unmakes the new being.
198
- async boot(maker, className, key, id) {
199
- if ((await this.#make(key, className)) !== 'booted')
200
- return null;
201
- if (id === undefined)
202
- return key;
203
- const invitation = await this.#residents.get(key).stance.occupants.invite(maker);
204
- const taken = invitation ? await this.#residents.get(maker)?.stance.standings.take(id, invitation) : null;
205
- if (taken)
206
- return key;
207
- this.#unboot(key);
208
- return null;
209
- }
210
- async #make(key, className) {
211
- if (key === '' || key === WARD || this.partition.being(key) || this.#birthing.has(key))
212
- return 'key taken';
213
- const C = this.#parts.catalogue.classOf(className);
214
- if (!C)
215
- return 'no such class';
216
- this.#birthing.add(key);
217
- try {
218
- const row = { class: className, cells: {}, occupants: {}, standings: {} };
219
- this.partition.beings[key] = row;
220
- if (!this.#bear(key, row, C)) {
221
- delete this.partition.beings[key];
222
- return 'threw at birth';
223
- }
224
- this.partition.told(key);
225
- return 'booted';
226
- }
227
- finally {
228
- this.#birthing.delete(key);
229
- }
230
- }
231
- #bear(key, row, C) {
232
- const stance = new WardStance(this, key, row);
233
- try {
234
- this.#residents.set(key, { being: new C(stance), row, stance });
235
- return true;
236
- }
237
- catch {
238
- this.#residents.delete(key);
239
- return false;
240
- }
241
- }
242
- #unboot(key) {
243
- const row = key === WARD ? undefined : this.partition.being(key);
244
- if (!row)
245
- return false;
246
- for (const { heir } of Object.values(row.occupants)) {
247
- this.door.remove(heir);
248
- delete this.partition.head.bind[heir];
249
- }
250
- if (this.partition.head.public === key)
251
- this.partition.head.public = null;
252
- delete this.partition.beings[key];
253
- this.#residents.delete(key);
254
- this.partition.toldHead();
255
- this.partition.told(key);
256
- return true;
257
- }
258
- // What the ward-being asks of her ward.
259
- #steward = {
260
- pk: () => this.pk,
261
- classOf: (name) => this.#parts.catalogue.classOf(name),
262
- beings: () => {
263
- const out = {};
264
- for (const [key, row] of Object.entries(this.partition.beings)) {
265
- if (key !== WARD)
266
- out[key] = { class: row.class, public: this.partition.head.public === key, absent: !this.#residents.has(key) };
267
- }
268
- return out;
269
- },
270
- boot: (key, className) => this.#make(key, className),
271
- unboot: (key) => this.#unboot(key),
272
- publish: (key) => {
273
- if (key !== null && (key === WARD || !this.partition.being(key)))
274
- return false;
275
- this.partition.head.public = key;
276
- this.partition.toldHead();
277
- return true;
278
- },
279
- invite: (being, id, notes) => {
280
- const resident = being === WARD ? undefined : this.#residents.get(being);
281
- return resident ? resident.stance.occupants.invite(id, notes) : Promise.resolve(null);
282
- },
283
- ask: (being, method, args) => {
284
- const key = being ?? this.partition.head.public;
285
- if (key === null || key === WARD)
286
- return Promise.resolve(word('unreached'));
287
- return this.#answer(key, being === null ? {} : { id: OWNER }, method, args);
288
- },
289
- };
290
- }
package/src/cli/main.ts DELETED
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env node
2
- // SPDX-License-Identifier: Apache-2.0
3
- // The `nervur` program: `command.ts` over this process's arguments. A
4
- // command that cannot run exits 2 and says why on stderr.
5
- import { main, SERVING } from './command.ts';
6
-
7
- try {
8
- const code = await main(process.argv.slice(2), process.env, (line) => process.stdout.write(`${line}\n`));
9
- if (code !== SERVING) process.exitCode = code;
10
- } catch (e) {
11
- process.stderr.write(`nervur: ${(e as Error).message}\n`);
12
- process.exitCode = 2;
13
- }
@@ -1,33 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // Web Crypto, read at every use. A page on a plain http origin has `crypto`
3
- // without `subtle`, and a terrain may install it after this module loads.
4
- export const subtle = (): SubtleCrypto => {
5
- const found = globalThis.crypto?.subtle;
6
- if (!found) throw new Error('this terrain has no crypto.subtle: a ward needs a secure context');
7
- return found;
8
- };
9
-
10
- export type Bytes = Uint8Array<ArrayBuffer>;
11
-
12
- // Web Crypto takes a buffer it owns, so every input is copied into one.
13
- export const own = (bytes: Uint8Array): Bytes => Uint8Array.from(bytes);
14
-
15
- // The PKCS#8 wrapping of a thirty-two byte secret, which is the whole of it
16
- // for both curves.
17
- const PKCS8 = { Ed25519: '302e020100300506032b657004220420', X25519: '302e020100300506032b656e04220420' } as const;
18
-
19
- export const importSecret = (curve: keyof typeof PKCS8, secret: Uint8Array, uses: KeyUsage[]): Promise<CryptoKey> => {
20
- if (secret.length !== 32) throw new TypeError('a secret is thirty-two bytes');
21
- const prefix = Uint8Array.from(PKCS8[curve].match(/../g)!, (b) => parseInt(b, 16));
22
- const wrapped = new Uint8Array(48);
23
- wrapped.set(prefix);
24
- wrapped.set(secret, 16);
25
- return subtle().importKey('pkcs8', wrapped, { name: curve }, true, uses);
26
- };
27
-
28
- // Web Crypto gives a private key's public half only through a JWK.
29
- export const publicOf = async (key: CryptoKey): Promise<Uint8Array> => {
30
- const { x } = await subtle().exportKey('jwk', key);
31
- const binary = atob(x!.replaceAll('-', '+').replaceAll('_', '/'));
32
- return Uint8Array.from(binary, (c) => c.charCodeAt(0));
33
- };
@@ -1,21 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // X25519 agrees. A secret is thirty-two bytes, clamped by the function and
3
- // never before.
4
- import { zero } from './bytes.ts';
5
- import { importSecret, own, publicOf, subtle } from './subtle.ts';
6
-
7
- export const x25519Public = async (secret: Uint8Array): Promise<Uint8Array> => publicOf(await importSecret('X25519', secret, ['deriveBits']));
8
-
9
- // The agreement, or null for a public key that takes no seal: one whose
10
- // agreement is thirty-two zero bytes, or one the terrain refuses to read.
11
- export const agree = async (secret: Uint8Array, pk: Uint8Array): Promise<Uint8Array | null> => {
12
- if (pk.length !== 32) return null;
13
- try {
14
- const mine = await importSecret('X25519', secret, ['deriveBits']);
15
- const theirs = await subtle().importKey('raw', own(pk), { name: 'X25519' }, false, []);
16
- const shared = new Uint8Array(await subtle().deriveBits({ name: 'X25519', public: theirs }, mine, 256));
17
- return zero(shared) ? null : shared;
18
- } catch {
19
- return null;
20
- }
21
- };