nervur 0.23.0 → 0.24.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 (157) hide show
  1. package/CONTRIBUTING.md +13 -0
  2. package/LICENSE +55 -202
  3. package/NOTICE +3 -8
  4. package/README.md +14 -156
  5. package/RELEASING.md +15 -0
  6. package/SECURITY.md +9 -0
  7. package/bin/nervur.js +6 -0
  8. package/package.json +26 -81
  9. package/AUTHORING.md +0 -935
  10. package/COMMAND.md +0 -179
  11. package/FACES.md +0 -280
  12. package/FACULTIES.md +0 -578
  13. package/GROUNDS.md +0 -315
  14. package/KIT-SPEC.md +0 -304
  15. package/WORLD.md +0 -195
  16. package/dist/app/app-ground.d.ts +0 -18
  17. package/dist/app/app-ground.js +0 -23
  18. package/dist/app/index.d.ts +0 -2
  19. package/dist/app/index.js +0 -5
  20. package/dist/app/native.d.ts +0 -11
  21. package/dist/app/native.js +0 -13
  22. package/dist/being/being.d.ts +0 -306
  23. package/dist/being/being.js +0 -20
  24. package/dist/being/covers.d.ts +0 -9
  25. package/dist/being/covers.js +0 -21
  26. package/dist/being/index.d.ts +0 -4
  27. package/dist/being/index.js +0 -6
  28. package/dist/being/need.d.ts +0 -49
  29. package/dist/being/need.js +0 -33
  30. package/dist/being/schema.d.ts +0 -100
  31. package/dist/being/schema.js +0 -132
  32. package/dist/being/table.d.ts +0 -48
  33. package/dist/being/table.js +0 -344
  34. package/dist/bench/bench-ground.d.ts +0 -73
  35. package/dist/bench/bench-ground.js +0 -153
  36. package/dist/bench/bench.d.ts +0 -101
  37. package/dist/bench/bench.js +0 -368
  38. package/dist/bench/fake-clock.d.ts +0 -17
  39. package/dist/bench/fake-clock.js +0 -34
  40. package/dist/bench/fake-memory.d.ts +0 -16
  41. package/dist/bench/fake-memory.js +0 -46
  42. package/dist/bench/fake-network.d.ts +0 -66
  43. package/dist/bench/fake-network.js +0 -222
  44. package/dist/bench/fake-unlock.d.ts +0 -6
  45. package/dist/bench/fake-unlock.js +0 -10
  46. package/dist/bench/index.d.ts +0 -3
  47. package/dist/bench/index.js +0 -5
  48. package/dist/bench/seeded.d.ts +0 -11
  49. package/dist/bench/seeded.js +0 -37
  50. package/dist/bench/settle.d.ts +0 -2
  51. package/dist/bench/settle.js +0 -49
  52. package/dist/bench/stewards.d.ts +0 -169
  53. package/dist/bench/stewards.js +0 -128
  54. package/dist/bodies/class-list.d.ts +0 -14
  55. package/dist/bodies/class-list.js +0 -33
  56. package/dist/bodies/joined-carry.d.ts +0 -29
  57. package/dist/bodies/joined-carry.js +0 -48
  58. package/dist/bodies/kept.d.ts +0 -44
  59. package/dist/bodies/kept.js +0 -91
  60. package/dist/bodies/noble-crypto.d.ts +0 -22
  61. package/dist/bodies/noble-crypto.js +0 -88
  62. package/dist/bodies/seed-keys.d.ts +0 -10
  63. package/dist/bodies/seed-keys.js +0 -42
  64. package/dist/bodies/strict-tools.d.ts +0 -10
  65. package/dist/bodies/strict-tools.js +0 -306
  66. package/dist/bodies/vouch.d.ts +0 -20
  67. package/dist/bodies/vouch.js +0 -71
  68. package/dist/bodies/web-carry.d.ts +0 -72
  69. package/dist/bodies/web-carry.js +0 -245
  70. package/dist/bodies/web-clock.d.ts +0 -12
  71. package/dist/bodies/web-clock.js +0 -33
  72. package/dist/browser/browser-ground.d.ts +0 -76
  73. package/dist/browser/browser-ground.js +0 -294
  74. package/dist/browser/index.d.ts +0 -4
  75. package/dist/browser/index.js +0 -7
  76. package/dist/browser/indexeddb-memory.d.ts +0 -17
  77. package/dist/browser/indexeddb-memory.js +0 -97
  78. package/dist/browser/locked-unlock.d.ts +0 -24
  79. package/dist/browser/locked-unlock.js +0 -85
  80. package/dist/browser/origin-classes.d.ts +0 -7
  81. package/dist/browser/origin-classes.js +0 -31
  82. package/dist/edge/durable-clock.d.ts +0 -19
  83. package/dist/edge/durable-clock.js +0 -61
  84. package/dist/edge/durable-memory.d.ts +0 -5
  85. package/dist/edge/durable-memory.js +0 -11
  86. package/dist/edge/durable.d.ts +0 -18
  87. package/dist/edge/durable.js +0 -24
  88. package/dist/edge/edge-ground.d.ts +0 -49
  89. package/dist/edge/edge-ground.js +0 -223
  90. package/dist/edge/index.d.ts +0 -7
  91. package/dist/edge/index.js +0 -9
  92. package/dist/edge/native-crypto.d.ts +0 -8
  93. package/dist/edge/native-crypto.js +0 -102
  94. package/dist/edge/secret-unlock.d.ts +0 -7
  95. package/dist/edge/secret-unlock.js +0 -13
  96. package/dist/edge/socket-carry.d.ts +0 -39
  97. package/dist/edge/socket-carry.js +0 -111
  98. package/dist/foundation.d.ts +0 -162
  99. package/dist/foundation.js +0 -4
  100. package/dist/ground/dock.d.ts +0 -1460
  101. package/dist/ground/dock.js +0 -1159
  102. package/dist/ground/ground.d.ts +0 -239
  103. package/dist/ground/ground.js +0 -787
  104. package/dist/ground/views.d.ts +0 -76
  105. package/dist/ground/views.js +0 -208
  106. package/dist/house/crossing.d.ts +0 -50
  107. package/dist/house/crossing.js +0 -153
  108. package/dist/house/house.d.ts +0 -88
  109. package/dist/house/house.js +0 -2069
  110. package/dist/house/rows-shape.d.ts +0 -110
  111. package/dist/house/rows-shape.js +0 -12
  112. package/dist/house/rows.d.ts +0 -27
  113. package/dist/house/rows.js +0 -185
  114. package/dist/index.d.ts +0 -33
  115. package/dist/index.js +0 -29
  116. package/dist/node/bridge.d.ts +0 -20
  117. package/dist/node/bridge.js +0 -284
  118. package/dist/node/cli.d.ts +0 -2
  119. package/dist/node/cli.js +0 -225
  120. package/dist/node/file-memory.d.ts +0 -13
  121. package/dist/node/file-memory.js +0 -86
  122. package/dist/node/folder-classes.d.ts +0 -5
  123. package/dist/node/folder-classes.js +0 -40
  124. package/dist/node/gone.d.ts +0 -2
  125. package/dist/node/gone.js +0 -7
  126. package/dist/node/hand.d.ts +0 -39
  127. package/dist/node/hand.js +0 -107
  128. package/dist/node/http.d.ts +0 -11
  129. package/dist/node/http.js +0 -90
  130. package/dist/node/index.d.ts +0 -11
  131. package/dist/node/index.js +0 -13
  132. package/dist/node/ledger-memory.d.ts +0 -17
  133. package/dist/node/ledger-memory.js +0 -152
  134. package/dist/node/lock.d.ts +0 -10
  135. package/dist/node/lock.js +0 -78
  136. package/dist/node/node-ground.d.ts +0 -26
  137. package/dist/node/node-ground.js +0 -228
  138. package/dist/node/notify.d.ts +0 -1
  139. package/dist/node/notify.js +0 -18
  140. package/dist/node/shell.d.ts +0 -11
  141. package/dist/node/shell.js +0 -35
  142. package/dist/node/sync-folder.d.ts +0 -6
  143. package/dist/node/sync-folder.js +0 -18
  144. package/dist/node/tcp-carry.d.ts +0 -42
  145. package/dist/node/tcp-carry.js +0 -193
  146. package/dist/node/unlock.d.ts +0 -17
  147. package/dist/node/unlock.js +0 -86
  148. package/dist/node/websocket.d.ts +0 -12
  149. package/dist/node/websocket.js +0 -134
  150. package/dist/quo/frame.d.ts +0 -33
  151. package/dist/quo/frame.js +0 -92
  152. package/dist/quo/index.d.ts +0 -1
  153. package/dist/quo/index.js +0 -5
  154. package/dist/quo/room.d.ts +0 -154
  155. package/dist/quo/room.js +0 -362
  156. package/dist/serve/index.d.ts +0 -45
  157. package/dist/serve/index.js +0 -71
@@ -1,33 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // Classes from a plain list, each kind from the one class that declares it.
3
- import { declarationOf } from '../being/being.js';
4
- export class ClassList {
5
- #kinds = new Map();
6
- #steward;
7
- #public;
8
- constructor({ steward, public: open, beings = [] }) {
9
- const kindOf = (Class) => {
10
- const kind = declarationOf(Class)?.kind;
11
- if (typeof kind !== 'string')
12
- throw new TypeError('a class in the list is not a class of Being.of');
13
- const held = this.#kinds.get(kind);
14
- if (held !== undefined && held !== Class)
15
- throw new TypeError(`two classes claim the kind ${kind}`);
16
- this.#kinds.set(kind, Class);
17
- return kind;
18
- };
19
- this.#steward = kindOf(steward);
20
- this.#public = open === undefined ? undefined : kindOf(open);
21
- for (const Class of beings)
22
- kindOf(Class);
23
- }
24
- async resolve({ kind }) {
25
- return this.#kinds.get(kind);
26
- }
27
- steward() {
28
- return this.#steward;
29
- }
30
- public() {
31
- return this.#public;
32
- }
33
- }
@@ -1,29 +0,0 @@
1
- import type { Carry, Sent } from '../foundation.ts';
2
- export declare class JoinedCarry implements Carry {
3
- #private;
4
- /** `carries` by scheme: `{ tcp: tcpCarry, https: webCarry }`. */
5
- constructor(carries: Readonly<Record<string, Carry>>);
6
- /** A ward's door, hooked to every carry here that listens. */
7
- listen(options: {
8
- ward: string;
9
- door: (box: Uint8Array) => Promise<Uint8Array | null>;
10
- }): Promise<void>;
11
- /** A ward unhooked from every carry here that listens. */
12
- unlisten(options: {
13
- ward: string;
14
- }): void;
15
- send({ ward, at, box, wait }: {
16
- ward: string;
17
- at: readonly string[];
18
- box: Uint8Array;
19
- wait?: number;
20
- }): Promise<Sent>;
21
- at(options?: {
22
- toward?: string;
23
- }): readonly string[];
24
- /** Every domain any carry here reads as vouching, each once, in the carries' order. */
25
- vouched(options: {
26
- ward: string;
27
- at: readonly string[];
28
- }): Promise<readonly string[]>;
29
- }
@@ -1,48 +0,0 @@
1
- export class JoinedCarry {
2
- #carries;
3
- // Each carry once, where one serves two schemes, as the web serves http and https.
4
- #each;
5
- /** `carries` by scheme: `{ tcp: tcpCarry, https: webCarry }`. */
6
- constructor(carries) {
7
- this.#carries = new Map(Object.entries(carries));
8
- this.#each = [...new Set(this.#carries.values())];
9
- }
10
- /** A ward's door, hooked to every carry here that listens. */
11
- async listen(options) {
12
- for (const carry of this.#each)
13
- await carry.listen?.(options);
14
- }
15
- /** A ward unhooked from every carry here that listens. */
16
- unlisten(options) {
17
- for (const carry of this.#each)
18
- carry.unlisten?.(options);
19
- }
20
- async send({ ward, at, box, wait }) {
21
- const waiting = wait === undefined ? {} : { wait };
22
- // A carry that listens for the ward hands it the box by pointer, and no address is dialled.
23
- for (const carry of this.#each) {
24
- const sent = await carry.send({ ward, at: [], box, ...waiting });
25
- if (sent.reply !== null)
26
- return sent;
27
- }
28
- for (const address of at) {
29
- // A scheme is read in any case, as a URI's is.
30
- const scheme = address.slice(0, Math.max(0, address.indexOf('://'))).toLowerCase();
31
- const carry = this.#carries.get(scheme);
32
- if (carry === undefined)
33
- continue;
34
- const sent = await carry.send({ ward, at: [address], box, ...waiting });
35
- if (sent.reply !== null || sent.heard)
36
- return sent;
37
- }
38
- return { reply: null, heard: false };
39
- }
40
- at(options = {}) {
41
- return this.#each.flatMap((carry) => carry.at(options));
42
- }
43
- /** Every domain any carry here reads as vouching, each once, in the carries' order. */
44
- async vouched(options) {
45
- const each = await Promise.all(this.#each.map((carry) => carry.vouched(options)));
46
- return [...new Set(each.flat())];
47
- }
48
- }
@@ -1,44 +0,0 @@
1
- import type { Memory, PlaceRead } from '../foundation.ts';
2
- import type { Unlock } from '../ground/ground.ts';
3
- /** Secrets as text by name, kept where the terrain keeps them. */
4
- export interface Secrets {
5
- get(name: string): Promise<string | null>;
6
- set(name: string, value: string): Promise<void>;
7
- }
8
- /** A store of text by key, with a swap that lands only where nothing moved. */
9
- export interface Store {
10
- get(key: string): Promise<string | null>;
11
- /** Every key that begins with `prefix`. */
12
- keys(prefix: string): Promise<readonly string[]>;
13
- /**
14
- * Lands every write together, where every key in `expect` still holds
15
- * what it names, `null` for absent; otherwise lands nothing. A write of
16
- * `null` removes its key. Answers whether it landed.
17
- */
18
- swap(writes: Readonly<Record<string, string | null>>, expect: Readonly<Record<string, string | null>>): Promise<boolean>;
19
- }
20
- /** The ground's key among a terrain's secrets, drawn on first use. */
21
- export declare abstract class KeptUnlock implements Unlock {
22
- #private;
23
- constructor(secrets: Secrets);
24
- key(): Promise<string>;
25
- }
26
- /**
27
- * Memory over a store, one memory for each name. Each place is one key,
28
- * its entries as hex beside its version. Versions come from one counter
29
- * for the memory, so a place removed and written again never shows a
30
- * version it showed before. A write reads every place it names and swaps
31
- * them all against what it read.
32
- */
33
- export declare abstract class KeptMemory implements Memory {
34
- #private;
35
- constructor(store: Store, name: string);
36
- read({ place }: {
37
- place: string;
38
- }): Promise<PlaceRead>;
39
- list(): Promise<readonly string[]>;
40
- write({ writes, expect, }: {
41
- writes: Readonly<Record<string, Readonly<Record<string, Uint8Array | null>>>>;
42
- expect: Readonly<Record<string, string | null>>;
43
- }): Promise<Readonly<Record<string, string | null>> | null>;
44
- }
@@ -1,91 +0,0 @@
1
- const NAME = /^[a-z0-9][a-z0-9._-]{0,63}$/;
2
- const KEY = /^[0-9a-f]{64}$/;
3
- const hex = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');
4
- const bytes = (text) => new Uint8Array(text.match(/../g)?.map((pair) => parseInt(pair, 16)) ?? []);
5
- /** The ground's key among a terrain's secrets, drawn on first use. */
6
- export class KeptUnlock {
7
- #secrets;
8
- #drawn;
9
- constructor(secrets) {
10
- this.#secrets = secrets;
11
- }
12
- key() {
13
- // One key is drawn at a time, so two first uses never draw two.
14
- this.#drawn ??= (async () => {
15
- let key = await this.#secrets.get('nervur.key');
16
- if (key === null) {
17
- key = hex(crypto.getRandomValues(new Uint8Array(32)));
18
- await this.#secrets.set('nervur.key', key);
19
- }
20
- if (!KEY.test(key))
21
- throw new Error('the kept key is not sixty-four lowercase hex digits');
22
- return key;
23
- })();
24
- this.#drawn.catch(() => (this.#drawn = undefined));
25
- return this.#drawn;
26
- }
27
- }
28
- /**
29
- * Memory over a store, one memory for each name. Each place is one key,
30
- * its entries as hex beside its version. Versions come from one counter
31
- * for the memory, so a place removed and written again never shows a
32
- * version it showed before. A write reads every place it names and swaps
33
- * them all against what it read.
34
- */
35
- export class KeptMemory {
36
- #store;
37
- #prefix;
38
- constructor(store, name) {
39
- if (!NAME.test(name))
40
- throw new TypeError(`no memory is named ${name}`);
41
- this.#store = store;
42
- this.#prefix = `nervur/${name}/`;
43
- }
44
- #key(place) {
45
- return `${this.#prefix}p/${place}`;
46
- }
47
- async read({ place }) {
48
- const text = await this.#store.get(this.#key(place));
49
- if (text === null)
50
- return { entries: {}, version: null };
51
- const held = JSON.parse(text);
52
- return { entries: Object.fromEntries(Object.entries(held.e).map(([name, value]) => [name, bytes(value)])), version: String(held.v) };
53
- }
54
- async list() {
55
- const places = `${this.#prefix}p/`;
56
- return (await this.#store.keys(places)).map((key) => key.slice(places.length));
57
- }
58
- async write({ writes, expect, }) {
59
- const places = [...new Set([...Object.keys(writes), ...Object.keys(expect)])];
60
- const count = `${this.#prefix}count`;
61
- const held = { [count]: await this.#store.get(count) };
62
- for (const place of places)
63
- held[this.#key(place)] = await this.#store.get(this.#key(place));
64
- for (const place of places) {
65
- const text = held[this.#key(place)];
66
- const version = text === null ? null : String(JSON.parse(text).v);
67
- if (!(place in expect) || expect[place] !== version)
68
- return null;
69
- }
70
- let next = held[count] === null ? 0 : Number(held[count]);
71
- const landing = {};
72
- const versions = {};
73
- for (const [place, entries] of Object.entries(writes)) {
74
- const text = held[this.#key(place)];
75
- const kept = { ...(text === null ? {} : JSON.parse(text).e) };
76
- for (const [name, value] of Object.entries(entries)) {
77
- if (value === null)
78
- delete kept[name];
79
- else
80
- kept[name] = hex(value);
81
- }
82
- next += 1;
83
- const empty = Object.keys(kept).length === 0;
84
- landing[this.#key(place)] = empty ? null : JSON.stringify({ v: next, e: kept });
85
- versions[place] = empty ? null : String(next);
86
- }
87
- landing[count] = String(next);
88
- // What another writer moved since the read refuses the swap, as it would the versions.
89
- return (await this.#store.swap(landing, held)) ? versions : null;
90
- }
91
- }
@@ -1,22 +0,0 @@
1
- import type { Crypto } from '../foundation.ts';
2
- export declare class NobleCrypto implements Crypto {
3
- random(length: number): Uint8Array;
4
- sha256(data: Uint8Array): Promise<Uint8Array>;
5
- hkdf(ikm: Uint8Array, info: string, length: number): Promise<Uint8Array>;
6
- seal(key: Uint8Array, nonce: Uint8Array, plaintext: Uint8Array, additional: Uint8Array): Promise<Uint8Array>;
7
- open(key: Uint8Array, nonce: Uint8Array, ciphertext: Uint8Array, additional: Uint8Array): Promise<Uint8Array | null>;
8
- signingPublic(secret: Uint8Array): Promise<Uint8Array>;
9
- sign(secret: Uint8Array, message: Uint8Array): Promise<Uint8Array>;
10
- verify(pk: Uint8Array, message: Uint8Array, signature: Uint8Array): Promise<boolean>;
11
- agreePublic(secret: Uint8Array): Promise<Uint8Array>;
12
- agree(secret: Uint8Array, pk: Uint8Array): Promise<Uint8Array | null>;
13
- lockPair(seed: Uint8Array): Promise<{
14
- encapsulation: Uint8Array;
15
- decapsulation: Uint8Array;
16
- }>;
17
- encapsulate(encapsulation: Uint8Array): Promise<{
18
- ciphertext: Uint8Array;
19
- shared: Uint8Array;
20
- } | null>;
21
- decapsulate(decapsulation: Uint8Array, ciphertext: Uint8Array): Promise<Uint8Array>;
22
- }
@@ -1,88 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // The default crypto: Ed25519, X25519 and ML-KEM-768 from noble, SHA-256,
3
- // HKDF and AES-GCM from Web Crypto.
4
- import { ed25519, x25519 } from '@noble/curves/ed25519.js';
5
- import { ml_kem768 } from '@noble/post-quantum/ml-kem.js';
6
- const subtle = globalThis.crypto.subtle;
7
- const ascii = new TextEncoder();
8
- const view = (bytes) => new Uint8Array(bytes);
9
- export class NobleCrypto {
10
- random(length) {
11
- const out = new Uint8Array(length);
12
- for (let at = 0; at < length; at += 65_536)
13
- globalThis.crypto.getRandomValues(out.subarray(at, Math.min(length, at + 65_536)));
14
- return out;
15
- }
16
- async sha256(data) {
17
- return new Uint8Array(await subtle.digest('SHA-256', view(data)));
18
- }
19
- async hkdf(ikm, info, length) {
20
- const key = await subtle.importKey('raw', view(ikm), 'HKDF', false, ['deriveBits']);
21
- const bits = await subtle.deriveBits({ name: 'HKDF', hash: 'SHA-256', salt: new Uint8Array(0), info: ascii.encode(info) }, key, length * 8);
22
- return new Uint8Array(bits);
23
- }
24
- async seal(key, nonce, plaintext, additional) {
25
- const aes = await subtle.importKey('raw', view(key), 'AES-GCM', false, ['encrypt']);
26
- return new Uint8Array(await subtle.encrypt({ name: 'AES-GCM', iv: view(nonce), additionalData: view(additional) }, aes, view(plaintext)));
27
- }
28
- async open(key, nonce, ciphertext, additional) {
29
- if (ciphertext.length < 16)
30
- return null;
31
- const aes = await subtle.importKey('raw', view(key), 'AES-GCM', false, ['decrypt']);
32
- try {
33
- return new Uint8Array(await subtle.decrypt({ name: 'AES-GCM', iv: view(nonce), additionalData: view(additional) }, aes, view(ciphertext)));
34
- }
35
- catch {
36
- return null;
37
- }
38
- }
39
- async signingPublic(secret) {
40
- return ed25519.getPublicKey(secret);
41
- }
42
- async sign(secret, message) {
43
- return ed25519.sign(message, secret);
44
- }
45
- async verify(pk, message, signature) {
46
- if (pk.length !== 32 || signature.length !== 64)
47
- return false;
48
- try {
49
- // Strict decoding refuses a y at or above the prime and a non-canonical R.
50
- if (ed25519.Point.fromBytes(pk, false).isSmallOrder())
51
- return false;
52
- return ed25519.verify(signature, message, pk, { zip215: false });
53
- }
54
- catch {
55
- return false;
56
- }
57
- }
58
- async agreePublic(secret) {
59
- return x25519.getPublicKey(secret);
60
- }
61
- async agree(secret, pk) {
62
- if (pk.length !== 32)
63
- return null;
64
- try {
65
- const shared = x25519.getSharedSecret(secret, pk);
66
- return shared.every((byte) => byte === 0) ? null : shared;
67
- }
68
- catch {
69
- return null;
70
- }
71
- }
72
- async lockPair(seed) {
73
- const { publicKey, secretKey } = ml_kem768.keygen(seed);
74
- return { encapsulation: publicKey, decapsulation: secretKey };
75
- }
76
- async encapsulate(encapsulation) {
77
- try {
78
- const { cipherText, sharedSecret } = ml_kem768.encapsulate(encapsulation);
79
- return { ciphertext: cipherText, shared: sharedSecret };
80
- }
81
- catch {
82
- return null;
83
- }
84
- }
85
- async decapsulate(decapsulation, ciphertext) {
86
- return ml_kem768.decapsulate(ciphertext, decapsulation);
87
- }
88
- }
@@ -1,10 +0,0 @@
1
- import type { Crypto, Keys, WardKeys } from '../foundation.ts';
2
- export declare class SeedKeys implements Keys {
3
- #private;
4
- constructor(seed: string | undefined, crypto?: Crypto);
5
- ward(): Promise<WardKeys>;
6
- sign(message: Uint8Array): Promise<Uint8Array>;
7
- agree(pk: Uint8Array): Promise<Uint8Array | null>;
8
- decapsulate(ciphertext: Uint8Array): Promise<Uint8Array>;
9
- derive(label: string, length: number): Promise<Uint8Array>;
10
- }
@@ -1,42 +0,0 @@
1
- import { NobleCrypto } from './noble-crypto.js';
2
- const SEED = /^[0-9a-f]{64}$/;
3
- export class SeedKeys {
4
- #seed;
5
- #crypto;
6
- #held;
7
- constructor(seed, crypto = new NobleCrypto()) {
8
- if (typeof seed !== 'string' || !SEED.test(seed))
9
- throw new TypeError('a seed is sixty-four lowercase hex digits');
10
- this.#seed = Uint8Array.from(seed.match(/../g), (pair) => Number.parseInt(pair, 16));
11
- this.#crypto = crypto;
12
- }
13
- #keys() {
14
- this.#held ??= (async () => {
15
- const crypto = this.#crypto;
16
- const signing = await crypto.hkdf(this.#seed, 'quo-ward-sign', 32);
17
- const scalar = await crypto.hkdf(this.#seed, 'quo-ward-seal', 32);
18
- // The lock is the kit's: one per ward, drawn from the seed under a label of Nervur's.
19
- const lock = await crypto.lockPair(await crypto.hkdf(this.#seed, 'nervur-lock', 64));
20
- const ward = Object.freeze({ signing: await crypto.signingPublic(signing), padlock: await crypto.agreePublic(scalar), lock: lock.encapsulation });
21
- return { signing, scalar, decapsulation: lock.decapsulation, ward };
22
- })();
23
- return this.#held;
24
- }
25
- async ward() {
26
- return (await this.#keys()).ward;
27
- }
28
- async sign(message) {
29
- return this.#crypto.sign((await this.#keys()).signing, message);
30
- }
31
- async agree(pk) {
32
- return this.#crypto.agree((await this.#keys()).scalar, pk);
33
- }
34
- async decapsulate(ciphertext) {
35
- return this.#crypto.decapsulate((await this.#keys()).decapsulation, ciphertext);
36
- }
37
- async derive(label, length) {
38
- if (label.startsWith('quo-'))
39
- throw new TypeError('a label beginning quo- is Quo\'s');
40
- return this.#crypto.hkdf(this.#seed, `nervur-derive:${label}`, length);
41
- }
42
- }
@@ -1,10 +0,0 @@
1
- import type { Parsed, Tools } from '../foundation.ts';
2
- export declare class StrictTools implements Tools {
3
- utf8(text: string): Uint8Array;
4
- text(bytes: Uint8Array): string | null;
5
- hex(bytes: Uint8Array): string;
6
- bytes(hex: string): Uint8Array | null;
7
- parse(text: string): Parsed | null;
8
- canonical(value: unknown): string;
9
- check(schema: unknown, value: unknown): string | null;
10
- }